pykd

Форк
0
/
stkwalk.py 
296 строк · 8.5 Кб
1

2
import pykd
3
from pykd import *
4
from optparse import OptionParser
5
from fnmatch import fnmatch
6
import traceback
7
import sys
8
import datetime
9

10
nt = None
11
EPROCESS = None
12
ETHREAD = None
13
Tick = None
14

15
def setupGlobalObject():
16

17
    global nt, EPROCESS, ETHREAD, Tick
18

19
    try:
20
        nt = module("nt")
21
        EPROCESS = nt.type("_EPROCESS")
22
        ETHREAD = nt.type("_ETHREAD")
23
        if is64bitSystem():
24
            Tick = int(typedVar("nt!_LARGE_INTEGER", 0xFFFFF78000000320).QuadPart)
25
        else:
26
            Tick = int(ptrDWord(nt.KeTickCount))
27
        
28
    except DbgException:
29
        dprintln("check symbol paths")
30

31

32

33
class PrintOptions:
34
    def __init__(self):
35
        self.ignoreNotActiveThread = True
36
        self.ignoreNotActiveProcess = True
37
        self.showWow64stack = False
38
        self.showIP = True
39
        self.showSP = True
40
        self.showUnique = False
41
        self.combineWow64 = True
42
        self.showCpu = True
43
    
44
def printFrame(frame, printopt):
45

46
    str = ""
47

48
    if printopt.showCpu:
49
        str += frame.cpuType + "\t"
50

51
    if printopt.showIP:
52
        str += "%016x\t" % frame.instructionOffset
53
    if printopt.showSP:
54
        str += "%016x\t" % frame.stackOffset
55
    
56
    str +=  findSymbol( frame.instructionOffset )
57

58
    dprintln(str)
59

60

61
def getModule(offset):
62
    try:
63
        return module(offset)
64
    except DbgException:
65
        pass
66
    return None
67

68
def getStackHash(stk):
69
    hashStr = ""
70
    for frame in stk:
71
        hashStr += str(frame.instructionOffset)
72
    return hash(hashStr)
73

74
def getStackModules(stk):
75
    modules = []
76
    for frame in stk:
77
        m = getModule(frame.instructionOffset)
78
        if m and not ( m in modules ):
79
            modules.append( m )
80
    return modules
81

82
def getStackSymbols(stk):
83
    symbols = []
84
    for frame in stk:
85
        sym = findSymbol( frame.instructionOffset, showDisplacement = False )
86
        if sym and not ( sym in symbols ):
87
            symbols.append(sym)
88
    return symbols
89

90
def isWow64Process(process):
91
    result = False
92
    if is64bitSystem() == False:
93
        return result
94
    try:
95
        if hasattr(process, "WoW64Process"):
96
            return process.WoW64Process != 0
97
        elif hasattr(process, "Wow64Process"):
98
            return process.Wow64Process != 0
99
    except:
100
        pass
101
    
102
    return result
103

104

105
def printThread(thread, process, ticks):
106
    dprintln("")
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  )
108

109

110
def printProcess(process,processFilter,threadFilter,moduleFilter,funcFilter,printopt):
111

112
    processName = loadCStr( process.ImageFileName )
113
    processWow64 = isWow64Process(process)
114

115
    if processFilter and not processFilter(process, process.UniqueProcessId, processName ):
116
        return
117

118
    dprintln( "" )
119
    dprintln( "Process %x" %  process )
120
    dprintln( "Name: %s  Pid: %#x" %  ( processName, process.UniqueProcessId ) )
121
    dprintln( "" )
122

123
    wow64reloaded = False
124

125
    try:
126

127
        dbgCommand(".process /p /r %x" % process )
128
        dbgCommand( ".reload /user" )
129

130
        threadLst = typedVarList(process.ThreadListHead, ETHREAD, "ThreadListEntry.Flink")
131

132
        stackHashes = set()
133

134
        for thread in threadLst:
135
            
136
            ticks = Tick - thread.Tcb.WaitTime
137
            if threadFilter and not threadFilter( thread.Tcb, thread.Cid.UniqueThread, ticks ):
138
                continue
139

140
            try:
141

142
                setCurrentThread( thread )
143

144
                stkNative = getStack()
145
                stkWow64 = []
146

147
                if processWow64 and printopt.showWow64stack == True:
148

149
                    cpuMode = getCPUMode()
150

151
                    try:
152

153
                        dbgCommand(".thread /w %x" % thread)
154
                        #setCPUMode(CPUType.I386)
155

156
                        #if not wow64reloaded:
157
                        dbgCommand( ".reload /user" )
158
                        #    wow64reloaded = True
159
                        
160
                        stkWow64 = getStack()
161

162
                    except DbgException:
163
                        pass
164

165
                    setCPUMode(cpuMode)
166

167
            
168
                stk = []
169

170
                for frame in stkNative:
171

172
                    mod = getModule(frame.instructionOffset)
173

174
                    if mod and printopt.combineWow64 and stkWow64:
175
                        if mod.name() == "wow64cpu":
176
                            break
177

178
                    frame.cpuType = str(getCPUMode())
179
                    stk.append(frame)
180

181
                for frame in stkWow64:
182

183
                    frame.cpuType = "WOW64"
184
                    stk.append(frame)
185

186
                if printopt.showUnique:
187
                    stackHash= getStackHash(stk)
188
                    if stackHash in stackHashes:
189
                        continue
190
                    stackHashes.add( stackHash )
191

192
                if moduleFilter:
193
                    if not [ m for m in getStackModules(stk) if moduleFilter( m, m.name() ) ]:
194
                         continue
195

196
                if funcFilter:
197
                    match = False
198
                    for sym in getStackSymbols(stk):
199
                        if funcFilter(sym) or ( len( sym.split('!', 1) ) == 2 and funcFilter( sym.split('!', 1)[1] ) ):
200
                            match = True
201
                            break
202
                    if not match:
203
                        continue
204

205
                printThread( thread, process, ticks )
206

207
                for frame in stk:
208
                    printFrame(frame, printopt)
209

210
            except DbgException:
211

212
                printThread( thread, process, ticks )
213
                dprintln( "Failed to get stack")
214

215

216

217
    except DbgException:
218

219
        if not printopt.ignoreNotActiveProcess:
220

221
            dprintln( "Process %x" %  process )
222
            dprintln( "Name: %s" %  processName )
223
            dprintln( "Failed to switch into process context\n")
224
            dprintln( "" )  
225

226

227
def main():
228

229
    dprintln("Stack walker. ver 1.1")
230

231
    if not hasattr(pykd, "__version__") or not fnmatch( pykd.__version__, "0.3.*"):
232
        dprintln ( "pykd has incompatible version" )
233
  
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")
249
    
250
    (options, args) = parser.parse_args()
251

252
    if not isKernelDebugging():
253
       dprintln("This script is only for kernel debugging")
254
       return
255

256
    if not isWindbgExt():
257
        try:
258
            initialize()
259
        except DbgException:
260
            pass
261

262
        if getNumberProcesses() == 0:
263
            loadDump( options.dumpname )
264

265
    setupGlobalObject()
266

267
    processFilter = None
268
    moduleFilter = None
269
    funcFilter = None
270
    threadFilter = None
271
    
272
    if options.processfilter:
273
        processFilter = lambda process, pid, name: eval( options.processfilter )
274
        
275
    if options.modulefilter:
276
        moduleFilter = lambda module, name: eval(options.modulefilter)
277
        
278
    if options.funcfilter:
279
        funcFilter = lambda name: eval( options.funcfilter)
280
        
281
    if options.threadfilter:
282
        threadFilter = lambda thread, tid, ticks: eval( options.threadfilter)
283

284
    printopt = PrintOptions()
285
    printopt.showUnique = True if options.uniquestack else False
286

287
    if options.wow64 == True and is64bitSystem():
288
        printopt.showWow64stack = True
289

290
           
291
    processLst = nt.typedVarList( nt.PsActiveProcessHead, "_EPROCESS", "ActiveProcessLinks.Flink")  
292
    for process in processLst:
293
        printProcess( process, processFilter, threadFilter, moduleFilter, funcFilter, printopt )
294

295

296
if __name__ == "__main__":
297
    main()
298

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.