mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-19 19:13:22 +08:00
[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:
parent
bd19263aed
commit
d922dbe8da
@ -1,4 +1,5 @@
|
||||
|
||||
import pykd
|
||||
from pykd import *
|
||||
from optparse import OptionParser
|
||||
from fnmatch import fnmatch
|
||||
@ -6,6 +7,21 @@ import traceback
|
||||
import sys
|
||||
|
||||
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:
|
||||
def __init__(self):
|
||||
@ -15,129 +31,59 @@ class PrintOptions:
|
||||
self.showIP = True
|
||||
self.showSP = True
|
||||
self.showUnique = False
|
||||
|
||||
def applayThreadFilter(thread,threadFilter,moduleFilter,funcFilter,printopt,stackHashes):
|
||||
|
||||
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
|
||||
self.combineWow64 = True
|
||||
self.showCpu = True
|
||||
|
||||
def printFrame(frame, printopt):
|
||||
|
||||
str = ""
|
||||
|
||||
if printopt.showCpu:
|
||||
str += frame.cpuType + "\t"
|
||||
|
||||
if printopt.showIP:
|
||||
dprint( "%016x\t" % frame.instructionOffset )
|
||||
str += "%016x\t" % frame.instructionOffset
|
||||
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:
|
||||
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 ) )
|
||||
for frame in stk:
|
||||
printFrame(frame, printopt)
|
||||
def getStackModules(stk):
|
||||
modules = []
|
||||
for frame in stk:
|
||||
m = getModule(frame.instructionOffset)
|
||||
if m and not ( m in modules ):
|
||||
modules.append( m )
|
||||
return modules
|
||||
|
||||
if is64bitSystem():
|
||||
processorMode = getProcessorMode()
|
||||
try:
|
||||
setProcessorMode("X86")
|
||||
stk = getStackWow64()
|
||||
dprintln("\nWOW64 stack")
|
||||
for frame in stk:
|
||||
printFrame(frame, printopt)
|
||||
except BaseException:
|
||||
pass
|
||||
setProcessorMode(processorMode)
|
||||
def getStackSymbols(stk):
|
||||
symbols = []
|
||||
for frame in stk:
|
||||
sym = findSymbol( frame.instructionOffset, showDisplacement = False )
|
||||
if sym and not ( sym in symbols ):
|
||||
symbols.append(sym)
|
||||
return symbols
|
||||
|
||||
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):
|
||||
@ -147,32 +93,93 @@ def printProcess(process,processFilter,threadFilter,moduleFilter,funcFilter,prin
|
||||
if processFilter and not processFilter(process, process.UniqueProcessId, processName ):
|
||||
return
|
||||
|
||||
try:
|
||||
#setCurrentProcess(process)
|
||||
dbgCommand(".process /p %x" % process )
|
||||
dprintln( "Process %x" % process )
|
||||
dprintln( "Name: %s Pid: %#x" % ( processName, process.UniqueProcessId ) )
|
||||
dprintln( "" )
|
||||
|
||||
try:
|
||||
|
||||
dbgCommand(".process /p /r %x" % process )
|
||||
dbgCommand( ".reload /user" )
|
||||
|
||||
threadLst = nt.typedVarList(process.ThreadListHead, "_ETHREAD", "ThreadListEntry.Flink")
|
||||
filteredThreadLst = []
|
||||
threadLst = typedVarList(process.ThreadListHead, ETHREAD, "ThreadListEntry.Flink")
|
||||
|
||||
stackHashes = set()
|
||||
|
||||
for thread in threadLst:
|
||||
if applayThreadFilter( thread, threadFilter, moduleFilter, funcFilter, printopt, stackHashes ):
|
||||
filteredThreadLst.append( thread )
|
||||
|
||||
if filteredThreadLst == []:
|
||||
return
|
||||
if threadFilter and not threadFilter( thread.Tcb, thread.Cid.UniqueThread ):
|
||||
continue
|
||||
|
||||
dprintln( "Process %x" % process )
|
||||
dprintln( "Name: %s Pid: %#x" % ( processName, process.UniqueProcessId ) )
|
||||
dprintln( "" )
|
||||
setCurrentThread( thread )
|
||||
|
||||
for thread in filteredThreadLst:
|
||||
printThread(process,thread, printopt)
|
||||
stkNative = getStack()
|
||||
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:
|
||||
|
||||
dprintln( "Process %x" % process )
|
||||
dprintln( "Name: %s" % processName )
|
||||
dprintln( "Failed to switch into process context\n")
|
||||
@ -180,14 +187,11 @@ def printProcess(process,processFilter,threadFilter,moduleFilter,funcFilter,prin
|
||||
|
||||
|
||||
def main():
|
||||
dprintln("Stack walker. ver 1.0")
|
||||
|
||||
if not isKernelDebugging():
|
||||
dprintln("This script is only for kernel debugging")
|
||||
return
|
||||
dprintln("Stack walker. ver 1.1")
|
||||
|
||||
global nt
|
||||
nt = module("nt")
|
||||
if not hasattr(pykd, "__version__") or not fnmatch( pykd.__version__, "0.3.*"):
|
||||
dprintln ( "pykd has incompatible version" )
|
||||
|
||||
parser = OptionParser()
|
||||
parser.add_option("-p", "--process", dest="processfilter",
|
||||
@ -195,14 +199,28 @@ def main():
|
||||
parser.add_option("-m", "--module", dest="modulefilter",
|
||||
help="module filter: boolean expression with python syntax" )
|
||||
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",
|
||||
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",
|
||||
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()
|
||||
|
||||
if not isWindbgExt():
|
||||
initialize()
|
||||
loadDump( options.dumpname )
|
||||
|
||||
if not isKernelDebugging():
|
||||
dprintln("This script is only for kernel debugging")
|
||||
return
|
||||
|
||||
setupGlobalObject()
|
||||
|
||||
processFilter = None
|
||||
moduleFilter = None
|
||||
funcFilter = None
|
||||
@ -223,16 +241,14 @@ def main():
|
||||
printopt = PrintOptions()
|
||||
printopt.showUnique = True if options.uniquestack else False
|
||||
|
||||
currentProcess = getCurrentProcess()
|
||||
currentThread = getImplicitThread()
|
||||
if options.wow64 != None:
|
||||
printopt.showWow64stack = options.wow64.lower() == 'true'
|
||||
|
||||
|
||||
processLst = nt.typedVarList( nt.PsActiveProcessHead, "_EPROCESS", "ActiveProcessLinks.Flink")
|
||||
for process in processLst:
|
||||
printProcess( process, processFilter, threadFilter, moduleFilter, funcFilter, printopt )
|
||||
|
||||
setCurrentProcess(currentProcess)
|
||||
setImplicitThread(currentThread)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
Loading…
Reference in New Issue
Block a user