forked from OSchip/llvm-project
143 lines
5.8 KiB
Python
143 lines
5.8 KiB
Python
|
##===-- 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
|