4
from optparse import OptionParser
5
from fnmatch import fnmatch
15
def setupGlobalObject():
17
global nt, EPROCESS, ETHREAD, Tick
21
EPROCESS = nt.type("_EPROCESS")
22
ETHREAD = nt.type("_ETHREAD")
24
Tick = int(typedVar("nt!_LARGE_INTEGER", 0xFFFFF78000000320).QuadPart)
26
Tick = int(ptrDWord(nt.KeTickCount))
29
dprintln("check symbol paths")
35
self.ignoreNotActiveThread = True
36
self.ignoreNotActiveProcess = True
37
self.showWow64stack = False
40
self.showUnique = False
41
self.combineWow64 = True
44
def printFrame(frame, printopt):
49
str += frame.cpuType + "\t"
52
str += "%016x\t" % frame.instructionOffset
54
str += "%016x\t" % frame.stackOffset
56
str += findSymbol( frame.instructionOffset )
71
hashStr += str(frame.instructionOffset)
74
def getStackModules(stk):
77
m = getModule(frame.instructionOffset)
78
if m and not ( m in modules ):
82
def getStackSymbols(stk):
85
sym = findSymbol( frame.instructionOffset, showDisplacement = False )
86
if sym and not ( sym in symbols ):
90
def isWow64Process(process):
92
if is64bitSystem() == False:
95
if hasattr(process, "WoW64Process"):
96
return process.WoW64Process != 0
97
elif hasattr(process, "Wow64Process"):
98
return process.Wow64Process != 0
105
def printThread(thread, process, ticks):
107
dprintln( "<link cmd=\".process %x;.thread %x\">Thread %x</link>, Process: %s (%x), Ticks: %d" % ( process, thread, thread, loadCStr( process.ImageFileName ), process, ticks ), True )
110
def printProcess(process,processFilter,threadFilter,moduleFilter,funcFilter,printopt):
112
processName = loadCStr( process.ImageFileName )
113
processWow64 = isWow64Process(process)
115
if processFilter and not processFilter(process, process.UniqueProcessId, processName ):
119
dprintln( "Process %x" % process )
120
dprintln( "Name: %s Pid: %#x" % ( processName, process.UniqueProcessId ) )
123
wow64reloaded = False
127
dbgCommand(".process /p /r %x" % process )
128
dbgCommand( ".reload /user" )
130
threadLst = typedVarList(process.ThreadListHead, ETHREAD, "ThreadListEntry.Flink")
134
for thread in threadLst:
136
ticks = Tick - thread.Tcb.WaitTime
137
if threadFilter and not threadFilter( thread.Tcb, thread.Cid.UniqueThread, ticks ):
142
setCurrentThread( thread )
144
stkNative = getStack()
147
if processWow64 and printopt.showWow64stack == True:
149
cpuMode = getCPUMode()
153
dbgCommand(".thread /w %x" % thread)
157
dbgCommand( ".reload /user" )
160
stkWow64 = getStack()
170
for frame in stkNative:
172
mod = getModule(frame.instructionOffset)
174
if mod and printopt.combineWow64 and stkWow64:
175
if mod.name() == "wow64cpu":
178
frame.cpuType = str(getCPUMode())
181
for frame in stkWow64:
183
frame.cpuType = "WOW64"
186
if printopt.showUnique:
187
stackHash= getStackHash(stk)
188
if stackHash in stackHashes:
190
stackHashes.add( stackHash )
193
if not [ m for m in getStackModules(stk) if moduleFilter( m, m.name() ) ]:
198
for sym in getStackSymbols(stk):
199
if funcFilter(sym) or ( len( sym.split('!', 1) ) == 2 and funcFilter( sym.split('!', 1)[1] ) ):
205
printThread( thread, process, ticks )
208
printFrame(frame, printopt)
212
printThread( thread, process, ticks )
213
dprintln( "Failed to get stack")
219
if not printopt.ignoreNotActiveProcess:
221
dprintln( "Process %x" % process )
222
dprintln( "Name: %s" % processName )
223
dprintln( "Failed to switch into process context\n")
229
dprintln("Stack walker. ver 1.1")
231
if not hasattr(pykd, "__version__") or not fnmatch( pykd.__version__, "0.3.*"):
232
dprintln ( "pykd has incompatible version" )
234
parser = OptionParser()
235
parser.add_option("-p", "--process", dest="processfilter",
236
help="process filter: boolean expression with python syntax" )
237
parser.add_option("-m", "--module", dest="modulefilter",
238
help="module filter: boolean expression with python syntax" )
239
parser.add_option("-f", "--function", dest="funcfilter",
240
help="function filter: boolean expression with python syntax" )
241
parser.add_option("-t", "--thread", dest="threadfilter",
242
help="thread filter: boolean expresion with python syntax" )
243
parser.add_option("-u", "--unique", action="store_true", dest="uniquestack",
244
help="show only unique stacks" )
245
parser.add_option("-d", "--dump", dest="dumpname",
246
help="open crash dump" )
247
parser.add_option("-w", "--wow64", action="store_true", dest="wow64",
248
help="show WOW64 stacks")
250
(options, args) = parser.parse_args()
252
if not isKernelDebugging():
253
dprintln("This script is only for kernel debugging")
256
if not isWindbgExt():
262
if getNumberProcesses() == 0:
263
loadDump( options.dumpname )
272
if options.processfilter:
273
processFilter = lambda process, pid, name: eval( options.processfilter )
275
if options.modulefilter:
276
moduleFilter = lambda module, name: eval(options.modulefilter)
278
if options.funcfilter:
279
funcFilter = lambda name: eval( options.funcfilter)
281
if options.threadfilter:
282
threadFilter = lambda thread, tid, ticks: eval( options.threadfilter)
284
printopt = PrintOptions()
285
printopt.showUnique = True if options.uniquestack else False
287
if options.wow64 == True and is64bitSystem():
288
printopt.showWow64stack = True
291
processLst = nt.typedVarList( nt.PsActiveProcessHead, "_EPROCESS", "ActiveProcessLinks.Flink")
292
for process in processLst:
293
printProcess( process, processFilter, threadFilter, moduleFilter, funcFilter, printopt )
296
if __name__ == "__main__":