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