📄 phpdebugger.py
字号:
elif (cause == None):
Exception.__init__(self, msg)
else:
Exception.__init__(self, "PHPDBGException: message:%s\n, cause:%s" % (msg, cause))
class PHPDBGConnException(PHPDBGException):
pass
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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -