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