2013-10-12 01:13:07 +08:00
|
|
|
##===-- debuggerdriver.py ------------------------------------*- Python -*-===##
|
|
|
|
##
|
|
|
|
## The LLVM Compiler Infrastructure
|
|
|
|
##
|
|
|
|
## This file is distributed under the University of Illinois Open Source
|
|
|
|
## License. See LICENSE.TXT for details.
|
|
|
|
##
|
|
|
|
##===----------------------------------------------------------------------===##
|
|
|
|
|
2013-10-10 06:11:30 +08:00
|
|
|
|
|
|
|
import lldb
|
|
|
|
import lldbutil
|
|
|
|
import sys
|
|
|
|
from threading import Thread
|
|
|
|
|
|
|
|
class DebuggerDriver(Thread):
|
|
|
|
""" Drives the debugger and responds to events. """
|
|
|
|
def __init__(self, debugger, event_queue):
|
|
|
|
Thread.__init__(self)
|
|
|
|
self.event_queue = event_queue
|
|
|
|
# This is probably not great because it does not give liblldb a chance to clean up
|
|
|
|
self.daemon = True
|
|
|
|
self.initialize(debugger)
|
|
|
|
|
|
|
|
def initialize(self, debugger):
|
|
|
|
self.done = False
|
|
|
|
self.debugger = debugger
|
|
|
|
self.listener = debugger.GetListener()
|
|
|
|
if not self.listener.IsValid():
|
|
|
|
raise "Invalid listener"
|
|
|
|
|
|
|
|
self.listener.StartListeningForEventClass(self.debugger,
|
|
|
|
lldb.SBTarget.GetBroadcasterClassName(),
|
|
|
|
lldb.SBTarget.eBroadcastBitBreakpointChanged
|
|
|
|
#| lldb.SBTarget.eBroadcastBitModuleLoaded
|
|
|
|
#| lldb.SBTarget.eBroadcastBitModuleUnloaded
|
|
|
|
| lldb.SBTarget.eBroadcastBitWatchpointChanged
|
|
|
|
#| lldb.SBTarget.eBroadcastBitSymbolLoaded
|
|
|
|
)
|
|
|
|
|
|
|
|
self.listener.StartListeningForEventClass(self.debugger,
|
|
|
|
lldb.SBThread.GetBroadcasterClassName(),
|
|
|
|
lldb.SBThread.eBroadcastBitStackChanged
|
|
|
|
# lldb.SBThread.eBroadcastBitBreakpointChanged
|
|
|
|
| lldb.SBThread.eBroadcastBitThreadSuspended
|
|
|
|
| lldb.SBThread.eBroadcastBitThreadResumed
|
|
|
|
| lldb.SBThread.eBroadcastBitSelectedFrameChanged
|
|
|
|
| lldb.SBThread.eBroadcastBitThreadSelected
|
|
|
|
)
|
|
|
|
|
|
|
|
self.listener.StartListeningForEventClass(self.debugger,
|
|
|
|
lldb.SBProcess.GetBroadcasterClassName(),
|
|
|
|
lldb.SBProcess.eBroadcastBitStateChanged
|
|
|
|
| lldb.SBProcess.eBroadcastBitInterrupt
|
|
|
|
| lldb.SBProcess.eBroadcastBitSTDOUT
|
|
|
|
| lldb.SBProcess.eBroadcastBitSTDERR
|
|
|
|
| lldb.SBProcess.eBroadcastBitProfileData
|
|
|
|
)
|
|
|
|
self.listener.StartListeningForEventClass(self.debugger,
|
|
|
|
lldb.SBCommandInterpreter.GetBroadcasterClass(),
|
|
|
|
lldb.SBCommandInterpreter.eBroadcastBitThreadShouldExit
|
|
|
|
| lldb.SBCommandInterpreter.eBroadcastBitResetPrompt
|
|
|
|
| lldb.SBCommandInterpreter.eBroadcastBitQuitCommandReceived
|
|
|
|
| lldb.SBCommandInterpreter.eBroadcastBitAsynchronousOutputData
|
|
|
|
| lldb.SBCommandInterpreter.eBroadcastBitAsynchronousErrorData
|
|
|
|
)
|
|
|
|
def createTarget(self, target_image, args=None):
|
|
|
|
self.handleCommand("target create %s" % target_image)
|
|
|
|
if args is not None:
|
|
|
|
self.handleCommand("settings set target.run-args %s" % args)
|
|
|
|
|
|
|
|
def attachProcess(self, pid):
|
|
|
|
self.handleCommand("process attach -p %d" % pid)
|
|
|
|
pass
|
|
|
|
|
|
|
|
def loadCore(self, corefile):
|
|
|
|
self.handleCommand("target create -c %s" % corefile)
|
|
|
|
pass
|
|
|
|
|
|
|
|
def setDone(self):
|
|
|
|
self.done = True
|
|
|
|
|
|
|
|
def isDone(self):
|
|
|
|
return self.done
|
|
|
|
|
|
|
|
def getPrompt(self):
|
|
|
|
return self.debugger.GetPrompt()
|
|
|
|
|
|
|
|
def getCommandInterpreter(self):
|
|
|
|
return self.debugger.GetCommandInterpreter()
|
|
|
|
|
|
|
|
def getSourceManager(self):
|
|
|
|
return self.debugger.GetSourceManager()
|
|
|
|
|
|
|
|
def setSize(self, width, height):
|
|
|
|
# FIXME: respect height
|
|
|
|
self.debugger.SetTerminalWidth(width)
|
|
|
|
|
|
|
|
def getTarget(self):
|
|
|
|
return self.debugger.GetTargetAtIndex(0)
|
|
|
|
|
|
|
|
def handleCommand(self, cmd):
|
|
|
|
ret = lldb.SBCommandReturnObject()
|
|
|
|
self.getCommandInterpreter().HandleCommand(cmd, ret)
|
|
|
|
return ret
|
|
|
|
|
|
|
|
def eventLoop(self):
|
|
|
|
while not self.isDone():
|
|
|
|
event = lldb.SBEvent()
|
|
|
|
got_event = self.listener.WaitForEvent(lldb.UINT32_MAX, event)
|
|
|
|
if got_event and not event.IsValid():
|
|
|
|
self.winAddStr("Warning: Invalid or no event...")
|
|
|
|
continue
|
|
|
|
elif not event.GetBroadcaster().IsValid():
|
|
|
|
continue
|
|
|
|
|
|
|
|
self.event_queue.put(event)
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
self.eventLoop()
|
|
|
|
|
|
|
|
def terminate(self):
|
|
|
|
lldb.SBDebugger.Terminate()
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
def createDriver(debugger, event_queue):
|
|
|
|
driver = DebuggerDriver(debugger, event_queue)
|
|
|
|
#driver.start()
|
|
|
|
# if pid specified:
|
|
|
|
# - attach to pid
|
|
|
|
# else if core file specified
|
|
|
|
# - create target from corefile
|
|
|
|
# else
|
|
|
|
# - create target from file
|
|
|
|
# - settings append target.run-args <args-from-cmdline>
|
|
|
|
# source .lldbinit file
|
|
|
|
|
|
|
|
return driver
|