📄 phpdebugger.py
字号:
class PHPDebuggerCallback(object): ACTION_NONE = 0 ACTION_STOP = 1 ACTION_LISTEN = 2 def __init__(self, ui, service, lsnrHosti, lsnrPorti): self.ui = ui self.service = service self.lsnrHost = lsnrHosti self.lsnrPort = lsnrPorti self.lsnrThr = None self.lsnrAction = PHPDebuggerCallback.ACTION_NONE self.clearInternals() self.initLsnrThr() ############################################################################ # Public callback functions begin # def Start(self): self.lsnrThr.start() def ShutdownServer(self, stopLsnr = True): # # First to tell php debugger to stop execution of the current PHP # program. Disconnect with php dbg module too. # self.stopPhpDbg() # # Stop debug listener. # if stopLsnr: self.stopLsnr() def BreakExecution(self): reqPacket = PHPDBGPacket(IntToC4(DBGC_PAUSE)) try: reqPacket.sendPacket(self.lsnrThr) self.awaitAndHandleResponse() except PHPDBGConnException: self.currConnFinished() return self.ui.LoadPHPFramesList(self.stackList) return def SingleStep(self): reqPacket = PHPDBGPacket(DBGA_STEPINTO) try: reqPacket.sendPacket(self.lsnrThr) self.lastCommand = DBGA_STEPINTO self.awaitAndHandleResponse(blocking = True) except PHPDBGConnException: self.currConnFinished() return self.ui.LoadPHPFramesList(self.stackList) return def Next(self): reqPacket = PHPDBGPacket(DBGA_STEPOVER) try: reqPacket.sendPacket(self.lsnrThr) self.lastCommand = DBGA_STEPOVER self.awaitAndHandleResponse(blocking = True) except PHPDBGConnException: self.currConnFinished() return self.ui.LoadPHPFramesList(self.stackList) return def Continue(self): reqPacket = PHPDBGPacket(DBGA_CONTINUE) try: reqPacket.sendPacket(self.lsnrThr) self.lastCommand = DBGA_CONTINUE self.awaitAndHandleResponse(blocking = True) except PHPDBGConnException: self.currConnFinished() return self.ui.LoadPHPFramesList(self.stackList) return def Return(self): reqPacket = PHPDBGPacket(DBGA_STEPOUT) try: reqPacket.sendPacket(self.lsnrThr) self.lastCommand = DBGA_STEPOUT self.awaitAndHandleResponse(blocking = True) except PHPDBGConnException: self.currConnFinished() return self.ui.LoadPHPFramesList(self.stackList) return def PushBreakpoints(self, noRemove = False): tmpList = [] bps = self.service.GetMasterBreakpointDict() for fileName in bps.keys(): if fileName.endswith('.php'): lines = bps[fileName] if lines: for lineNo in lines: if lineNo: # # A tuple (fileName, lineNo) is an item which is # used as a key in self.bpDict. # tmpList.append(self.createBpKey(fileName, lineNo)) myprint("PushBreakpoints(): global breakpoint \'%s:%i\'", (fileName, lineNo)) # # Check to see if we have any new breakpoints added. # for oneKey in tmpList: if not self.bpDict.has_key(oneKey): # # A new breakpoint. # newBp = BreakPoint(self, oneKey[0], oneKey[1]) newBp.addSelf() self.bpDict[oneKey] = newBp myprint("PushBreakpoints(): newly added global breakpoint \'%s:%i\'", (oneKey[0], oneKey[1])) if noRemove: return # # Check to see if any bp that is in our list, but not in the latest # global list. If so, it must have been removed recently in the # global one. Remove it from our list and tell php debugger to do # so as well. # toRemoveList = [] for oneKey in self.bpDict.keys(): if tmpList.count(oneKey) == 0: toRemoveList.append((oneKey, self.bpDict[oneKey])) myprint("PushBreakpoints(): recently removed global breakpoint \'%s:%i\'", (oneKey[0], oneKey[1])) for bp in toRemoveList: bp[1].removeSelf() del self.bpDict[bp[0]] myprint("PushBreakpoints(): successfully removed breakpoint \'%s:%i\' from both our local list and php debugger", (bp[0][0], bp[0][1])) return # # Public callback functions end ############################################################################ def newConnEventHandler(self): # # Ok, we've got a connection from the php debugger, and some initial # frame data from it. Everything is ready and let's make some initial # actions. # self.clearInternals() try: self.awaitAndHandleResponse(self.lsnrThr.getConnHeader()) except PHPDBGConnException: self.currConnFinished() return self.PushBreakpoints(True) self.ui.LoadPHPFramesList(self.stackList) # # This could be called when this object is constructed or when self is # re-initialized after getting a new dbg module connection as a new # session. # def clearInternals(self): self.stackList = [] self.errStackList = [] self.stackFrameIndex = 0 self.isErrStack = False self.errStr = '' self.modList = [] self.stopOnError = True self.lastCommand = None self.evalRet = '' self.modDict = {} self.bpDict = {} self.rawDataDict = {} self.sessID = 0 self.sessType = 0 self.sessEnded = False self.frameCounter = 1000 self.variableList = [] self.verMajor = 0 self.verMinor = 0 self.verDesc = None def initLsnrThr(self): self.actionEvent = threading.Event() self.lsnrThr = PHPDBGLsnrThr(self, self.lsnrHost, self.lsnrPort, self.actionEvent, self.ui) def awaitAndHandleResponse(self, header = None, blocking = False, disable = True, stopping = False): if disable: self.ui.DisableWhileDebuggerRunning() while self.readResponse(header, blocking) != 0: myprint("Waiting for response") if stopping: self.ui.DisableAfterStop() else: self.ui.EnableWhileDebuggerStopped() def requestDBGVersion(self): #TODO: necessary? pass def getSourceTree(self): #TODO: necessary? pass def addDBGModName(self): #TODO: necessary? pass def getNextFrameCounter(self): self.frameCounter = self.frameCounter + 1 return self.frameCounter def getVariables(self, stack): self.variableList = [] reqPacket = PHPDBGPacket(DBGA_REQUEST) reqFrame = PHPDBGFrame(FRAME_EVAL) reqFrame.addInt(0) reqFrame.addInt(stack.getFrameScopeId()) reqPacket.addFrame(reqFrame) myprint("PHPDebuggerCallback::getVariables(): about to send eval request") try: reqPacket.sendPacket(self.lsnrThr) self.awaitAndHandleResponse(disable = False) except PHPDBGConnException: self.currConnFinished() return self.variableList myprint("PHPDebuggerCallback::getVariables(): evalRet=%s", self.evalRet) evalStr = PHPDBGEvalString(stack, self.evalRet) if evalStr: self.variableList = evalStr.getVars() myprint("PHPDebuggerCallback::getVariables(): about to return") return self.variableList def evalBlock(self, stack, evalStr): reqPacket = PHPDBGPacket(DBGA_REQUEST) reqFrame1 = PHPDBGFrame(FRAME_EVAL) reqFrame2 = PHPDBGFrame(FRAME_RAWDATA) frameID = self.getNextFrameCounter() reqFrame1.addInt(frameID) reqFrame1.addInt(1) reqFrame2.addInt(frameID) reqFrame2.addInt(len(evalStr) + 1) reqFrame2.addStr(evalString) reqPacket.addFrame(reqFrame2) reqPacket.addFrame(reqFrame1) try: reqPacket.sendPacket(self.lsnrThr) self.awaitAndHandleResponse(disable = False) except PHPDBGConnException: self.currConnFinished() return None evalStr = PHPDBGEvalString(stack, self.evalRet) return evalStr.getVars() def getBPUnderHit(self): for bp in self.bpDict.values(): if bp.isUnderHit(): return bp return None def getRawFrameData(self, frameNo): if self.rawDataDict.has_key(frameNo): # # Once the frameData is consumed, remove it from rawDataDict. # return self.rawDataDict.pop(frameNo) else: # # TODO: do we need to handle the case when the raw frame data hasn't # been received before? # return None def getModByNum(self, modNum): if self.modDict.has_key(modNum): return self.modDict[modNum] else: return None def getModByFileName(self, fileName): for mn, fn in self.modDict.iteritems(): if fn == fileName: return mn return 0 def setMod(self, modNum, fileName): if modNum != 0 and fileName: self.modDict[modNum] = fileName return def readResponse(self, headeri = None, blockingi = False): inHeader = headeri header = None cmdReceived = 0 isFirstPacket = True blocking = blockingi self.isErrStack = False self.rawDataDict.clear() while True: # # If we have already received the first packet, we can't block any # more. # if not isFirstPacket: blocking = False # # If this is the first loop and we have a non-empty header passed in, use it. Otherwise, # read in a new header. For subsequent loops, inHeader is None so we always read a new # header from the wire. # if inHeader: header = inHeader inHeader = None else: header = ResponseHeader(self.lsnrThr, blocking) if not header.isValid: return 0 cmdReceived = header.command frame = ResponsePacketFrame(self.lsnrThr, header.toRead, None, blocking) if not frame.isValid: return 0 isFirstPacket = False isFirstStackFrame = True while frame and frame.isValid: frameName = frame.frameName if frameName == FRAME_STACK: if self.isErrStack: self.errStackList = self.handleRespFrameStack(self.errStackList, frame, isFirstStackFrame) else: self.stackList = self.handleRespFrameStack(self.stackList, frame, isFirstStackFrame) if isFirstStackFrame: isFirstStackFrame = False elif frameName == FRAME_SOURCE: self.handleRespFrameSource(frame) elif frameName == FRAME_SRC_TREE: self.handleRespFrameSrcTree(frame) elif frameName == FRAME_RAWDATA: self.handleRespFrameRawdata(frame) elif frameName == FRAME_ERROR: self.handleRespFrameError(frame) elif frameName == FRAME_EVAL: self.handleRespFrameEval(frame) elif frameName == FRAME_BPS:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -