| ##===-- debuggerdriver.py ------------------------------------*- Python -*-===## |
| ## |
| # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| # See https://llvm.org/LICENSE.txt for license information. |
| # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| ## |
| ##===----------------------------------------------------------------------===## |
| |
| |
| 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 |