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