def constructor(jobs, glob_env, project): env_checker(glob_env) for name, settings in jobs.items(): job_config = settings.get("job_config", {}) or {} job_env = glob_env.copy() job_config_env = job_config.get("env", {}) or {} env_checker(job_config_env) job_env.update(job_config_env) job_config["env"] = job_env monitor_config = settings.get("monitor", {}) or {} if not monitor_config: raise ValueError("monitor field is empty at %s" % name) monitor_config["name"] = gen_hier(project, name) monitor_type = monitor_config.get("type", "") or "" if monitor_type == "svn": monitor = SvnMonitor(**monitor_config) elif monitor_type == "file": monitor = FileMonitor(**monitor_config) elif monitor_type == "scheduler": monitor = Scheduler(**monitor_config) else: raise TypeError( "This monitor type doesn't support: {0}".format(monitor_type)) continue_on_error = job_config.pop("continue_on_error", False) on_events = settings.get("on_events", None) or None if isinstance(on_events, dict): for event, callbacks in on_events.items(): if callbacks: config = copy.deepcopy(job_config) monitor.add_event(event, callbacks, config, continue_on_error) elif isinstance(on_events, list): config = copy.deepcopy(job_config) monitor.add_event(ANY_EVENT, on_events, config, continue_on_error) for signal in ("on_error", "on_success"): callback = settings.get(signal, None) if callback: config = copy.deepcopy(job_config) monitor.add_handler(signal, callback["name"], callback["cmd"], **config) yield monitor
def run(self): thread_created('<' + self.name + '>') sb_interpreter = self._debugger.GetCommandInterpreter() #listener = self._debugger.GetListener() listener = self.__listener listener.StartListeningForEventClass(self._debugger, lldb.SBTarget.GetBroadcasterClassName(), lldb.SBTarget.eBroadcastBitBreakpointChanged) # This isn't in Driver.cpp. Check why it listens to those events (because it uses SBDebugger's listener?) # listener.StartListeningForEventClass(self._debugger, # lldb.SBProcess.GetBroadcasterClassName(), # lldb.SBProcess.eBroadcastBitStateChanged | \ # lldb.SBProcess.eBroadcastBitInterrupt | \ # lldb.SBProcess.eBroadcastBitSTDOUT | \ # lldb.SBProcess.eBroadcastBitSTDERR) # Warn whoever started us that we can start working self.broadcaster.BroadcastEventByType(LldbDriver.eBroadcastBitThreadDidStart) # Create pipes for communicating with the debugger in_pipe_fd, out_pipe_fd = os.pipe() self.__from_debugger_fh_r = os.fdopen(in_pipe_fd, 'r', 0) self.__from_debugger_fh_w = os.fdopen(out_pipe_fd, 'w', 0) in_pipe_fd, out_pipe_fd = os.pipe() self.__to_debugger_fh_r = os.fdopen(in_pipe_fd, 'r', 0) self.__to_debugger_fh_w = os.fdopen(out_pipe_fd, 'w', 0) self.__file_monitor = FileMonitor(self.__master_thread_bytes_received, self.__from_debugger_fh_r) self.debugger.SetOutputFileHandle(self.__from_debugger_fh_w, False) self.debugger.SetErrorFileHandle(self.__from_debugger_fh_w, False) self.debugger.SetInputFileHandle(self.__to_debugger_fh_r, False) # m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor); error = lldb.SBError(self.__input_reader.Initialize(self.debugger, self.__input_reader_callback, lldb.eInputReaderGranularityLine, None, # end token (NULL == never done) None, # Prompt (NULL == taken care of elsewhere) False)) # echo input (we'll take care of this elsewhere) if error.Fail(): # Fail now... We can't have any input reader sublime.error_message('error: ' + error.GetCString()) return self.debugger.PushInputReader(self.__input_reader) if listener.IsValid(): iochannel_thread_exited = False listener.StartListeningForEvents(self.io_channel.broadcaster, IOChannel.eBroadcastBitHasUserInput | \ IOChannel.eBroadcastBitUserInterrupt | \ IOChannel.eBroadcastBitThreadShouldExit | \ IOChannel.eBroadcastBitThreadDidStart | \ IOChannel.eBroadcastBitThreadDidExit) self.io_channel.start() if self.io_channel.is_alive(): listener.StartListeningForEvents(sb_interpreter.GetBroadcaster(), lldb.SBCommandInterpreter.eBroadcastBitQuitCommandReceived | \ lldb.SBCommandInterpreter.eBroadcastBitAsynchronousOutputData | \ lldb.SBCommandInterpreter.eBroadcastBitAsynchronousErrorData) result = lldb.SBCommandReturnObject() sb_interpreter.SourceInitFileInHomeDirectory(result) # TODO Remove this debugging feature and have a way to report # errors in init files. if True: result.PutError(self.debugger.GetErrorFileHandle()) result.PutOutput(self.debugger.GetOutputFileHandle()) sb_interpreter.SourceInitFileInCurrentWorkingDirectory(result) # TODO Remove this debugging feature and have a way to report # errors in init files. if True: result.PutError(self.debugger.GetErrorFileHandle()) result.PutOutput(self.debugger.GetOutputFileHandle()) event = lldb.SBEvent() listener.WaitForEventForBroadcasterWithType(BIG_TIMEOUT, self.io_channel.broadcaster, IOChannel.eBroadcastBitThreadDidStart, event) self.ready_for_command() while not self.is_done: listener.WaitForEvent(BIG_TIMEOUT, event) if event: if event.GetBroadcaster(): ev_type = event.GetType() if (event.BroadcasterMatchesRef(self.io_channel.broadcaster)): if ev_type & IOChannel.eBroadcastBitHasUserInput: command_string = lldb.SBEvent.GetCStringFromEvent(event) if command_string is None: command_string = '' result = lldb.SBCommandReturnObject() self.debugger.GetCommandInterpreter().HandleCommand(command_string, result, True) if result.GetOutputSize() > 0: self.io_channel.out_write(result.GetOutput(), IOChannel.NO_ASYNC) if result.GetErrorSize() > 0: self.io_channel.err_write(result.GetError(), IOChannel.NO_ASYNC) debug(debugDriver, 'waiting_for_command = False') self.__waiting_for_command = False if self.__input_reader.IsActive(): self.ready_for_command() elif ev_type & IOChannel.eBroadcastBitThreadShouldExit \ or ev_type & IOChannel.eBroadcastBitThreadDidExit: self.is_done = True if ev_type & IOChannel.eBroadcastBitThreadDidExit: iochannel_thread_exited = True else: # TODO: __handle_io_event is not implemented if self.__handle_io_event(event): self.is_done = True elif lldb.SBProcess.EventIsProcessEvent(event): self.__handle_process_event(event) elif lldb.SBBreakpoint.EventIsBreakpointEvent(event): self.__handle_breakpoint_event(event) elif event.BroadcasterMatchesRef(sb_interpreter.GetBroadcaster()): # This first one should be replaced with a CommandOverrideCallback function if ev_type & lldb.SBCommandInterpreter.eBroadcastBitQuitCommandReceived: self.is_done = True elif ev_type & lldb.SBCommandInterpreter.eBroadcastBitAsynchronousErrorData: data = lldb.SBEvent.GetCStringFromEvent(event) self.io_channel.err_write(data, IOChannel.ASYNC) lldb_view_send(stderr_msg(data)) elif ev_type & lldb.SBCommandInterpreter.eBroadcastBitAsynchronousOutputData: data = lldb.SBEvent.GetCStringFromEvent(event) self.io_channel.out_write(data, IOChannel.ASYNC) lldb_view_send(stdout_msg(data)) if not iochannel_thread_exited: event.Clear() listener.GetNextEventForBroadcasterWithType(self.io_channel.broadcaster, IOChannel.eBroadcastBitThreadDidExit, event) if not event: self.io_channel.stop() self.__file_monitor.setDone() # Ensure the listener (and everything else, really) is destroyed BEFORE the SBDebugger # Otherwise lldb will try to lock a destroyed mutex. # TODO: Track that bug! listener = None lldb.SBDebugger.Destroy(self.debugger) debug(debugDriver, 'leaving') set_driver_instance(None) if self.__on_exit_callback: self.__on_exit_callback()
class LldbDriver(threading.Thread): eBroadcastBitThreadShouldExit = 1 << 0 eBroadcastBitThreadDidStart = 1 << 1 eBroadcastBitReadyForInput = 1 << 2 __is_done = False __io_channel = None __broadcaster = None __input_reader = None __waiting_for_command = False # FIXME: This should be configurable __max_instructions = 200 ########################################## # Python object functions. def __init__(self, window, log_callback=None, process_stopped_callback=None, on_exit_callback=None): super(LldbDriver, self).__init__(name='sublime.lldb.driver') self.__window = window lldb.SBDebugger.Initialize() self.__broadcaster = lldb.SBBroadcaster('Driver') self.__process_stopped_callback = process_stopped_callback self.__on_exit_callback = on_exit_callback # if log_callback: # self._debugger = lldb.SBDebugger.Create(False, log_callback) # else: self._debugger = lldb.SBDebugger.Create(False) self.__listener = self._debugger.GetListener() set_driver_instance(self) r, w = os.pipe() self.__io_channel_r_fh = os.fdopen(r, 'r', 0) self.__io_channel_w_fh = os.fdopen(w, 'w', 0) self.__io_channel = IOChannel(self, self.__io_channel_r_fh, lldb_view_send) # self._debugger.SetCloseInputOnEOF(False) self.__input_reader = lldb.SBInputReader() def __del__(self): # del self.__io_channel # del self.__broadcaster # del self._debugger lldb.SBDebugger.Terminate() ########################################## # Driver properties. @property def debugger(self): """The low-level SBDebugger for this driver.""" return self._debugger @property def broadcaster(self): return self.__broadcaster @property def listener(self): return self.__listener @property def io_channel(self): """The IO channel for this driver.""" return self.__io_channel @io_channel.deleter def io_channel(self): del self.__io_channel @property def is_done(self): """True if the debugger has finished its work.""" return self.__is_done @is_done.setter def is_done(self, done): self.__is_done = done ########################################## # Process queries. def current_target(self): target = self.debugger.GetSelectedTarget() return target def current_process(self): target = self.current_target() if not target: return None process = target.GetProcess() return process def current_thread(self): process = self.current_process() if not process: return False thread = process.GetSelectedThread() return thread def current_frame(self): thread = self.current_thread() if not thread: return None frame = thread.GetSelectedFrame() return frame def get_PC(self): frame = self.current_frame() if not frame: return False target = frame.GetThread().GetProcess().GetTarget() return frame.GetPCAddress().GetLoadAddress(target) @property def line_entry(self): frame = self.current_frame() if not frame: return None entry = frame.GetLineEntry() filespec = entry.GetFileSpec() if filespec: return (filespec.GetDirectory(), filespec.GetFilename(), \ entry.GetLine()) else: return None def process_is_running(self, proc=None): if proc is None: proc = self.current_process() if proc: return proc.GetState() == lldb.eStateRunning return False def process_is_stopped(self, proc=None): if proc is None: proc = self.current_process() if proc: return proc.GetState() == lldb.eStateStopped return False def process_has_exited(self, proc=None): if proc is None: proc = self.current_process() if proc: return proc.GetState() == lldb.eStateExited return False def disassemble_selected_frame(self): frame = self.current_frame() return self.disassemble_frame(frame) def disassemble_frame(self, frame): if not frame: debug(debugDriver, 'Driver.disassemble_frame: not frame == True') return None target = frame.GetThread().GetProcess().GetTarget() pc = frame.GetPCAddress() function = pc.GetFunction() symbol = pc.GetSymbol() if function.IsValid(): code = function.GetInstructions(target) elif symbol.IsValid(): code = symbol.GetInstructions(target) else: code = target.ReadInstructions(pc, self.__max_instructions) result = [] for i in code: comment = i.GetComment(target) # data = i.GetData(target) # data_str = '' # if data.GetByteSize() > 0: # stream = lldb.SBStream() # error = lldb.SBError() # data.GetDescription(stream, data.GetAddress(error, 0)) # if error.Success(): # data_str = " (data: %s)" % stream.GetData() if len(comment) > 0: result.append((i.GetAddress().GetLoadAddress(target), i.GetMnemonic(target), i.GetOperands(target), comment)) else: result.append((i.GetAddress().GetLoadAddress(target), i.GetMnemonic(target), i.GetOperands(target))) return result def get_breakpoint_locations_for_file(self, filename): bp_iter = self.current_target().breakpoint_iter() def filter(bp_loc): addr = bp_loc.GetAddress() if addr: line_entry = addr.GetLineEntry() if line_entry: filespec = line_entry.GetFileSpec() if filespec: filespec_path = filespec.GetDirectory() + '/' + filespec.GetFilename() return filespec_path == filename lst = [bp_loc for bp in bp_iter for bp_loc in bp if filter(bp_loc)] return lst ########################################## # Process I/O methods. def get_process_stdout(self): string = stdout_msg(self.debugger.GetSelectedTarget(). \ GetProcess().GetSTDOUT(1024)) while len(string) > 0: lldb_view_send(string) string = stdout_msg(self.debugger.GetSelectedTarget(). \ GetProcess().GetSTDOUT(1024)) def get_process_stderr(self): string = stderr_msg(self.debugger.GetSelectedTarget(). \ GetProcess().GetSTDOUT(1024)) while len(string) > 0: lldb_view_send(string) string = stderr_msg(self.debugger.GetSelectedTarget(). \ GetProcess().GetSTDOUT(1024)) ########################################## # Driver input methods. def maybe_get_input(self): if self.is_ready_for_command() and self.debugger.InputReaderIsTopReader(self.__input_reader): LldbInputDelegate.get_input(self.__window, '(lldb)') return True else: LldbInputDelegate.get_input(self.__window, '?') return True def is_ready_for_command(self): return self.__waiting_for_command def ready_for_command(self): """Send an eBroadcastBitReadyForInput if the debugger wasn't ready before this call.""" debug(debugDriver, 'ready for command. was waiting: ' + str(self.__waiting_for_command)) if not self.__waiting_for_command: self.__waiting_for_command = True self.broadcaster.BroadcastEventByType(LldbDriver.eBroadcastBitReadyForInput, False) def send_input(self, cmd): """Send a command asynchronously to the IO channel.""" self.__to_debugger_fh_w.write(bytes(cmd) + '\n') self.__to_debugger_fh_w.flush() # event = lldb.SBEvent(IOChannel.eBroadcastBitHasUserInput, str(cmd)) # self.io_channel.broadcaster.BroadcastEvent(event) def __input_reader_callback(self, input_reader, notification, bytes): if (notification == lldb.eInputReaderReactivate): self.ready_for_command() elif (notification == lldb.eInputReaderGotToken): # We're using a Line granularity. We don't receive the \n self.__io_channel_w_fh.write(bytes + '\n') self.__io_channel_w_fh.flush() elif (notification == lldb.eInputReaderAsynchronousOutputWritten): io_channel = self.io_channel if io_channel: pass # io_channel.refresh_prompt() elif (notification == lldb.eInputReaderInterrupt): io_channel = self.io_channel if io_channel: io_channel.out_write('^C\n', io_channel.NO_ASYNC) # io_channel.refresh_prompt() elif (notification == lldb.eInputReaderEndOfFile): io_channel = self.io_channel if io_channel: io_channel.out_write('^D\n', io_channel.NO_ASYNC) # io_channel.refresh_prompt() self.__io_channel_w_fh.write(b'quit\n') elif (notification == lldb.eInputReaderActivate): pass elif (notification == lldb.eInputReaderDeactivate): # Another input reader got pushed onto the stack # Let's open an input prompt for it. LldbInputDelegate.get_input(self.__window, '?') elif (notification == lldb.eInputReaderDone): pass def notif_str(): return [ "eInputReaderActivate, // reader is newly pushed onto the reader stack ", "eInputReaderAsynchronousOutputWritten, // an async output event occurred; the reader may want to do something", "eInputReaderReactivate, // reader is on top of the stack again after another reader was popped off ", "eInputReaderDeactivate, // another reader was pushed on the stack", "eInputReaderGotToken, // reader got one of its tokens (granularity)", "eInputReaderInterrupt, // reader received an interrupt signal (probably from a control-c)", "eInputReaderEndOfFile, // reader received an EOF char (probably from a control-d)", "eInputReaderDone // reader was just popped off the stack and is done"][notification] return len(bytes) def __master_thread_bytes_received(self, string): self.io_channel.out_write(string, IOChannel.ASYNC) ########################################## # Driver run loop. def run(self): thread_created('<' + self.name + '>') sb_interpreter = self._debugger.GetCommandInterpreter() #listener = self._debugger.GetListener() listener = self.__listener listener.StartListeningForEventClass(self._debugger, lldb.SBTarget.GetBroadcasterClassName(), lldb.SBTarget.eBroadcastBitBreakpointChanged) # This isn't in Driver.cpp. Check why it listens to those events (because it uses SBDebugger's listener?) # listener.StartListeningForEventClass(self._debugger, # lldb.SBProcess.GetBroadcasterClassName(), # lldb.SBProcess.eBroadcastBitStateChanged | \ # lldb.SBProcess.eBroadcastBitInterrupt | \ # lldb.SBProcess.eBroadcastBitSTDOUT | \ # lldb.SBProcess.eBroadcastBitSTDERR) # Warn whoever started us that we can start working self.broadcaster.BroadcastEventByType(LldbDriver.eBroadcastBitThreadDidStart) # Create pipes for communicating with the debugger in_pipe_fd, out_pipe_fd = os.pipe() self.__from_debugger_fh_r = os.fdopen(in_pipe_fd, 'r', 0) self.__from_debugger_fh_w = os.fdopen(out_pipe_fd, 'w', 0) in_pipe_fd, out_pipe_fd = os.pipe() self.__to_debugger_fh_r = os.fdopen(in_pipe_fd, 'r', 0) self.__to_debugger_fh_w = os.fdopen(out_pipe_fd, 'w', 0) self.__file_monitor = FileMonitor(self.__master_thread_bytes_received, self.__from_debugger_fh_r) self.debugger.SetOutputFileHandle(self.__from_debugger_fh_w, False) self.debugger.SetErrorFileHandle(self.__from_debugger_fh_w, False) self.debugger.SetInputFileHandle(self.__to_debugger_fh_r, False) # m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor); error = lldb.SBError(self.__input_reader.Initialize(self.debugger, self.__input_reader_callback, lldb.eInputReaderGranularityLine, None, # end token (NULL == never done) None, # Prompt (NULL == taken care of elsewhere) False)) # echo input (we'll take care of this elsewhere) if error.Fail(): # Fail now... We can't have any input reader sublime.error_message('error: ' + error.GetCString()) return self.debugger.PushInputReader(self.__input_reader) if listener.IsValid(): iochannel_thread_exited = False listener.StartListeningForEvents(self.io_channel.broadcaster, IOChannel.eBroadcastBitHasUserInput | \ IOChannel.eBroadcastBitUserInterrupt | \ IOChannel.eBroadcastBitThreadShouldExit | \ IOChannel.eBroadcastBitThreadDidStart | \ IOChannel.eBroadcastBitThreadDidExit) self.io_channel.start() if self.io_channel.is_alive(): listener.StartListeningForEvents(sb_interpreter.GetBroadcaster(), lldb.SBCommandInterpreter.eBroadcastBitQuitCommandReceived | \ lldb.SBCommandInterpreter.eBroadcastBitAsynchronousOutputData | \ lldb.SBCommandInterpreter.eBroadcastBitAsynchronousErrorData) result = lldb.SBCommandReturnObject() sb_interpreter.SourceInitFileInHomeDirectory(result) # TODO Remove this debugging feature and have a way to report # errors in init files. if True: result.PutError(self.debugger.GetErrorFileHandle()) result.PutOutput(self.debugger.GetOutputFileHandle()) sb_interpreter.SourceInitFileInCurrentWorkingDirectory(result) # TODO Remove this debugging feature and have a way to report # errors in init files. if True: result.PutError(self.debugger.GetErrorFileHandle()) result.PutOutput(self.debugger.GetOutputFileHandle()) event = lldb.SBEvent() listener.WaitForEventForBroadcasterWithType(BIG_TIMEOUT, self.io_channel.broadcaster, IOChannel.eBroadcastBitThreadDidStart, event) self.ready_for_command() while not self.is_done: listener.WaitForEvent(BIG_TIMEOUT, event) if event: if event.GetBroadcaster(): ev_type = event.GetType() if (event.BroadcasterMatchesRef(self.io_channel.broadcaster)): if ev_type & IOChannel.eBroadcastBitHasUserInput: command_string = lldb.SBEvent.GetCStringFromEvent(event) if command_string is None: command_string = '' result = lldb.SBCommandReturnObject() self.debugger.GetCommandInterpreter().HandleCommand(command_string, result, True) if result.GetOutputSize() > 0: self.io_channel.out_write(result.GetOutput(), IOChannel.NO_ASYNC) if result.GetErrorSize() > 0: self.io_channel.err_write(result.GetError(), IOChannel.NO_ASYNC) debug(debugDriver, 'waiting_for_command = False') self.__waiting_for_command = False if self.__input_reader.IsActive(): self.ready_for_command() elif ev_type & IOChannel.eBroadcastBitThreadShouldExit \ or ev_type & IOChannel.eBroadcastBitThreadDidExit: self.is_done = True if ev_type & IOChannel.eBroadcastBitThreadDidExit: iochannel_thread_exited = True else: # TODO: __handle_io_event is not implemented if self.__handle_io_event(event): self.is_done = True elif lldb.SBProcess.EventIsProcessEvent(event): self.__handle_process_event(event) elif lldb.SBBreakpoint.EventIsBreakpointEvent(event): self.__handle_breakpoint_event(event) elif event.BroadcasterMatchesRef(sb_interpreter.GetBroadcaster()): # This first one should be replaced with a CommandOverrideCallback function if ev_type & lldb.SBCommandInterpreter.eBroadcastBitQuitCommandReceived: self.is_done = True elif ev_type & lldb.SBCommandInterpreter.eBroadcastBitAsynchronousErrorData: data = lldb.SBEvent.GetCStringFromEvent(event) self.io_channel.err_write(data, IOChannel.ASYNC) lldb_view_send(stderr_msg(data)) elif ev_type & lldb.SBCommandInterpreter.eBroadcastBitAsynchronousOutputData: data = lldb.SBEvent.GetCStringFromEvent(event) self.io_channel.out_write(data, IOChannel.ASYNC) lldb_view_send(stdout_msg(data)) if not iochannel_thread_exited: event.Clear() listener.GetNextEventForBroadcasterWithType(self.io_channel.broadcaster, IOChannel.eBroadcastBitThreadDidExit, event) if not event: self.io_channel.stop() self.__file_monitor.setDone() # Ensure the listener (and everything else, really) is destroyed BEFORE the SBDebugger # Otherwise lldb will try to lock a destroyed mutex. # TODO: Track that bug! listener = None lldb.SBDebugger.Destroy(self.debugger) debug(debugDriver, 'leaving') set_driver_instance(None) if self.__on_exit_callback: self.__on_exit_callback() def stop(self): self.broadcaster.BroadcastEventByType(LldbDriver.eBroadcastBitThreadShouldExit) def __handle_breakpoint_event(self, ev): type = lldb.SBBreakpoint.GetBreakpointEventTypeFromEvent(ev) # TODO: Remove duplicate code for adding/deleting BP if type & lldb.eBreakpointEventTypeCommandChanged \ or type & lldb.eBreakpointEventTypeIgnoreChanged \ or type & lldb.eBreakpointEventTypeConditionChanged \ or type & lldb.eBreakpointEventTypeLocationsResolved: None elif type & lldb.eBreakpointEventTypeAdded: # TODO: show disabled bps bp = lldb.SBBreakpoint.GetBreakpointFromEvent(ev) for loc in bp: entry = None if loc and loc.GetAddress(): line_entry = loc.GetAddress().GetLineEntry() if line_entry: filespec = line_entry.GetFileSpec() if filespec: entry = (filespec.GetDirectory() + '/' + filespec.GetFilename(), \ line_entry.GetLine()) else: return None if entry: ui_updater().breakpoint_added(entry[0], entry[1], loc.IsEnabled()) elif type & lldb.eBreakpointEventTypeEnabled \ or type & lldb.eBreakpointEventTypeDisabled: bp = lldb.SBBreakpoint.GetBreakpointFromEvent(ev) for loc in bp: entry = None if loc and loc.GetAddress(): line_entry = loc.GetAddress().GetLineEntry() if line_entry: filespec = line_entry.GetFileSpec() if filespec: entry = (filespec.GetDirectory() + '/' + filespec.GetFilename(), \ line_entry.GetLine()) else: return None if entry: ui_updater().breakpoint_changed(entry[0], entry[1], loc.IsEnabled()) elif type & lldb.eBreakpointEventTypeRemoved: bp = lldb.SBBreakpoint.GetBreakpointFromEvent(ev) for loc in bp: entry = None if loc and loc.GetAddress(): line_entry = loc.GetAddress().GetLineEntry() if line_entry: filespec = line_entry.GetFileSpec() if filespec: entry = (filespec.GetDirectory() + '/' + filespec.GetFilename(), \ line_entry.GetLine()) else: return None if entry: ui_updater().breakpoint_removed(entry[0], entry[1], loc.IsEnabled()) elif type & lldb.eBreakpointEventTypeLocationsAdded: new_locs = lldb.SBBreakpoint.GetNumBreakpointLocationsFromEvent(ev) if new_locs > 0: bp = lldb.SBBreakpoint.GetBreakpointFromEvent(ev) lldb_view_send("%d locations added to breakpoint %d\n" % (new_locs, bp.GetID())) elif type & lldb.eBreakpointEventTypeLocationsRemoved: None def __handle_process_event(self, ev): type = ev.GetType() if type & lldb.SBProcess.eBroadcastBitSTDOUT: self.get_process_stdout() elif type & lldb.SBProcess.eBroadcastBitSTDOUT: self.get_process_stderr() elif type & lldb.SBProcess.eBroadcastBitInterrupt: debug(debugDriver, 'Got a process interrupt event!') lldbutil.get_description(ev) if self.__process_stopped_callback: self.__process_stopped_callback(self, lldb.SBProcess.GetProcessFromEvent(ev)) elif type & lldb.SBProcess.eBroadcastBitStateChanged: self.get_process_stdout() self.get_process_stderr() # only after printing the std* can we print our prompts state = lldb.SBProcess.GetStateFromEvent(ev) if state == lldb.eStateInvalid: return process = lldb.SBProcess.GetProcessFromEvent(ev) assert process.IsValid() if state == lldb.eStateInvalid \ or state == lldb.eStateUnloaded \ or state == lldb.eStateConnected \ or state == lldb.eStateAttaching \ or state == lldb.eStateLaunching \ or state == lldb.eStateStepping \ or state == lldb.eStateDetached: lldb_view_send("Process %llu %s\n", process.GetProcessID(), self.debugger.StateAsCString(state)) elif state == lldb.eStateRunning: None # Don't be too chatty elif state == lldb.eStateExited: debug(debugDriver, 'process state: ' + lldbutil.state_type_to_str(state)) r = self.interpret_command('process status') lldb_view_send(stdout_msg(r[0].GetOutput())) lldb_view_send(stderr_msg(r[0].GetError())) # Remove program counter markers if self.__process_stopped_callback: self.__process_stopped_callback(self, process, state) elif state == lldb.eStateStopped \ or state == lldb.eStateCrashed \ or state == lldb.eStateSuspended: debug(debugDriver, 'process state: ' + lldbutil.state_type_to_str(state)) if state != lldb.eStateStopped else None if lldb.SBProcess.GetRestartedFromEvent(ev): lldb_view_send('Process %llu stopped and was programmatically restarted.' % process.GetProcessID()) else: self.__update_selected_thread() if self.__process_stopped_callback: self.__process_stopped_callback(self, process, state) def __update_selected_thread(self): debugger = self.debugger proc = debugger.GetSelectedTarget().GetProcess() if proc.IsValid(): curr_thread = proc.GetSelectedThread() current_thread_stop_reason = curr_thread.GetStopReason() other_thread = lldb.SBThread() plan_thread = lldb.SBThread() if not curr_thread.IsValid() \ or current_thread_stop_reason == lldb.eStopReasonInvalid \ or current_thread_stop_reason == lldb.eStopReasonNone: for t in proc: t_stop_reason = t.GetStopReason() if t_stop_reason == lldb.eStopReasonInvalid \ or t_stop_reason == lldb.eStopReasonNone: pass elif t_stop_reason == lldb.eStopReasonTrace \ or t_stop_reason == lldb.eStopReasonBreakpoint \ or t_stop_reason == lldb.eStopReasonWatchpoint \ or t_stop_reason == lldb.eStopReasonSignal \ or t_stop_reason == lldb.eStopReasonException: debug(debugDriver, 'thread stop reason: ' + lldbutil.stop_reason_to_str(current_thread_stop_reason)) if not other_thread: other_thread = t elif t_stop_reason == lldb.eStopReasonPlanComplete: if not plan_thread: plan_thread = t if plan_thread: proc.SetSelectedThread(plan_thread) elif other_thread: proc.SetSelectedThread(other_thread) else: if curr_thread: thread = curr_thread else: thread = proc.GetThreadAtIndex(0) proc.SetSelectedThread(thread) ########################################## # Driver interaction. def interpret_command(self, cmd, add_to_history=False): result = lldb.SBCommandReturnObject() ci = self.debugger.GetCommandInterpreter() r = ci.HandleCommand(str(cmd), result, add_to_history) return (result, r)