1*061da546Spatrick##===-- debuggerdriver.py ------------------------------------*- Python -*-===## 2*061da546Spatrick## 3*061da546Spatrick# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*061da546Spatrick# See https://llvm.org/LICENSE.txt for license information. 5*061da546Spatrick# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*061da546Spatrick## 7*061da546Spatrick##===----------------------------------------------------------------------===## 8*061da546Spatrick 9*061da546Spatrick 10*061da546Spatrickimport lldb 11*061da546Spatrickimport lldbutil 12*061da546Spatrickimport sys 13*061da546Spatrickfrom threading import Thread 14*061da546Spatrick 15*061da546Spatrick 16*061da546Spatrickclass DebuggerDriver(Thread): 17*061da546Spatrick """ Drives the debugger and responds to events. """ 18*061da546Spatrick 19*061da546Spatrick def __init__(self, debugger, event_queue): 20*061da546Spatrick Thread.__init__(self) 21*061da546Spatrick self.event_queue = event_queue 22*061da546Spatrick # This is probably not great because it does not give liblldb a chance 23*061da546Spatrick # to clean up 24*061da546Spatrick self.daemon = True 25*061da546Spatrick self.initialize(debugger) 26*061da546Spatrick 27*061da546Spatrick def initialize(self, debugger): 28*061da546Spatrick self.done = False 29*061da546Spatrick self.debugger = debugger 30*061da546Spatrick self.listener = debugger.GetListener() 31*061da546Spatrick if not self.listener.IsValid(): 32*061da546Spatrick raise "Invalid listener" 33*061da546Spatrick 34*061da546Spatrick self.listener.StartListeningForEventClass(self.debugger, 35*061da546Spatrick lldb.SBTarget.GetBroadcasterClassName(), 36*061da546Spatrick lldb.SBTarget.eBroadcastBitBreakpointChanged 37*061da546Spatrick #| lldb.SBTarget.eBroadcastBitModuleLoaded 38*061da546Spatrick #| lldb.SBTarget.eBroadcastBitModuleUnloaded 39*061da546Spatrick | lldb.SBTarget.eBroadcastBitWatchpointChanged 40*061da546Spatrick #| lldb.SBTarget.eBroadcastBitSymbolLoaded 41*061da546Spatrick ) 42*061da546Spatrick 43*061da546Spatrick self.listener.StartListeningForEventClass(self.debugger, 44*061da546Spatrick lldb.SBThread.GetBroadcasterClassName(), 45*061da546Spatrick lldb.SBThread.eBroadcastBitStackChanged 46*061da546Spatrick # lldb.SBThread.eBroadcastBitBreakpointChanged 47*061da546Spatrick | lldb.SBThread.eBroadcastBitThreadSuspended 48*061da546Spatrick | lldb.SBThread.eBroadcastBitThreadResumed 49*061da546Spatrick | lldb.SBThread.eBroadcastBitSelectedFrameChanged 50*061da546Spatrick | lldb.SBThread.eBroadcastBitThreadSelected 51*061da546Spatrick ) 52*061da546Spatrick 53*061da546Spatrick self.listener.StartListeningForEventClass(self.debugger, 54*061da546Spatrick lldb.SBProcess.GetBroadcasterClassName(), 55*061da546Spatrick lldb.SBProcess.eBroadcastBitStateChanged 56*061da546Spatrick | lldb.SBProcess.eBroadcastBitInterrupt 57*061da546Spatrick | lldb.SBProcess.eBroadcastBitSTDOUT 58*061da546Spatrick | lldb.SBProcess.eBroadcastBitSTDERR 59*061da546Spatrick | lldb.SBProcess.eBroadcastBitProfileData 60*061da546Spatrick ) 61*061da546Spatrick self.listener.StartListeningForEventClass(self.debugger, 62*061da546Spatrick lldb.SBCommandInterpreter.GetBroadcasterClass(), 63*061da546Spatrick lldb.SBCommandInterpreter.eBroadcastBitThreadShouldExit 64*061da546Spatrick | lldb.SBCommandInterpreter.eBroadcastBitResetPrompt 65*061da546Spatrick | lldb.SBCommandInterpreter.eBroadcastBitQuitCommandReceived 66*061da546Spatrick | lldb.SBCommandInterpreter.eBroadcastBitAsynchronousOutputData 67*061da546Spatrick | lldb.SBCommandInterpreter.eBroadcastBitAsynchronousErrorData 68*061da546Spatrick ) 69*061da546Spatrick 70*061da546Spatrick def createTarget(self, target_image, args=None): 71*061da546Spatrick self.handleCommand("target create %s" % target_image) 72*061da546Spatrick if args is not None: 73*061da546Spatrick self.handleCommand("settings set target.run-args %s" % args) 74*061da546Spatrick 75*061da546Spatrick def attachProcess(self, pid): 76*061da546Spatrick self.handleCommand("process attach -p %d" % pid) 77*061da546Spatrick pass 78*061da546Spatrick 79*061da546Spatrick def loadCore(self, corefile): 80*061da546Spatrick self.handleCommand("target create -c %s" % corefile) 81*061da546Spatrick pass 82*061da546Spatrick 83*061da546Spatrick def setDone(self): 84*061da546Spatrick self.done = True 85*061da546Spatrick 86*061da546Spatrick def isDone(self): 87*061da546Spatrick return self.done 88*061da546Spatrick 89*061da546Spatrick def getPrompt(self): 90*061da546Spatrick return self.debugger.GetPrompt() 91*061da546Spatrick 92*061da546Spatrick def getCommandInterpreter(self): 93*061da546Spatrick return self.debugger.GetCommandInterpreter() 94*061da546Spatrick 95*061da546Spatrick def getSourceManager(self): 96*061da546Spatrick return self.debugger.GetSourceManager() 97*061da546Spatrick 98*061da546Spatrick def setSize(self, width, height): 99*061da546Spatrick # FIXME: respect height 100*061da546Spatrick self.debugger.SetTerminalWidth(width) 101*061da546Spatrick 102*061da546Spatrick def getTarget(self): 103*061da546Spatrick return self.debugger.GetTargetAtIndex(0) 104*061da546Spatrick 105*061da546Spatrick def handleCommand(self, cmd): 106*061da546Spatrick ret = lldb.SBCommandReturnObject() 107*061da546Spatrick self.getCommandInterpreter().HandleCommand(cmd, ret) 108*061da546Spatrick return ret 109*061da546Spatrick 110*061da546Spatrick def eventLoop(self): 111*061da546Spatrick while not self.isDone(): 112*061da546Spatrick event = lldb.SBEvent() 113*061da546Spatrick got_event = self.listener.WaitForEvent(lldb.UINT32_MAX, event) 114*061da546Spatrick if got_event and not event.IsValid(): 115*061da546Spatrick self.winAddStr("Warning: Invalid or no event...") 116*061da546Spatrick continue 117*061da546Spatrick elif not event.GetBroadcaster().IsValid(): 118*061da546Spatrick continue 119*061da546Spatrick 120*061da546Spatrick self.event_queue.put(event) 121*061da546Spatrick 122*061da546Spatrick def run(self): 123*061da546Spatrick self.eventLoop() 124*061da546Spatrick 125*061da546Spatrick def terminate(self): 126*061da546Spatrick lldb.SBDebugger.Terminate() 127*061da546Spatrick sys.exit(0) 128*061da546Spatrick 129*061da546Spatrick 130*061da546Spatrickdef createDriver(debugger, event_queue): 131*061da546Spatrick driver = DebuggerDriver(debugger, event_queue) 132*061da546Spatrick # driver.start() 133*061da546Spatrick # if pid specified: 134*061da546Spatrick # - attach to pid 135*061da546Spatrick # else if core file specified 136*061da546Spatrick # - create target from corefile 137*061da546Spatrick # else 138*061da546Spatrick # - create target from file 139*061da546Spatrick # - settings append target.run-args <args-from-cmdline> 140*061da546Spatrick # source .lldbinit file 141*061da546Spatrick 142*061da546Spatrick return driver 143