##===-- debuggerdriver.py ------------------------------------*- Python -*-===## ## # The LLVM Compiler Infrastructure ## # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. ## ##===----------------------------------------------------------------------===## 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 # source .lldbinit file return driver