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 process_stopped(driver, process, state=None): ui_updater().process_stopped(state, lambda: driver.maybe_get_input()) # Open a new view on source code/disassembly, if needed. if process and driver.process_is_stopped(process): filespec = None line_entry = process.GetSelectedThread().GetSelectedFrame( ).GetLineEntry() if line_entry: # We don't need to run 'process status' like Driver.cpp # Since we open the file and show the source line. r = driver.interpret_command('thread list') lldb_view_send(stdout_msg(r[0].GetOutput())) lldb_view_send(stderr_msg(r[0].GetError())) r = driver.interpret_command('frame info') lldb_view_send(stdout_msg(r[0].GetOutput())) lldb_view_send(stderr_msg(r[0].GetError())) filespec = line_entry.GetFileSpec() else: # Give us some assembly to check the crash/stop r = driver.interpret_command('process status') lldb_view_send(stdout_msg(r[0].GetOutput())) lldb_view_send(stderr_msg(r[0].GetError())) if not line_entry: # Get ALL the SBFrames t = process.GetSelectedThread() n = t.GetNumFrames() for i in xrange(0, n): f = t.GetFrameAtIndex(i) if f: line_entry = f.GetLineEntry() if line_entry and line_entry.GetFileSpec(): filespec = line_entry.GetFileSpec() if filespec: filename = filespec.GetDirectory() + '/' + filespec.GetFilename() # Maybe we don't need to focus the first group. The user knows # what he/she wants. def to_ui_thread(): window_ref().focus_group(0) v = window_ref().open_file(filename) lldb_view = get_lldb_view_for(v) if lldb_view is None: lldb_view = LLDBCodeView(v, driver) # TODO: Maybe bring the view to the front? sublime.set_timeout(to_ui_thread, 0) else: # TODO: If we don't have a filespec, we can try to disassemble # around the thread's PC. sublime.set_timeout( lambda: window_ref(). run_command('lldb_disassemble_frame', {'thread': process.GetSelectedThread()}), 0)
def process_stopped(driver, process, state=None): ui_updater().process_stopped(state, lambda: driver.maybe_get_input()) # Open a new view on source code/disassembly, if needed. if process and driver.process_is_stopped(process): filespec = None line_entry = process.GetSelectedThread().GetSelectedFrame().GetLineEntry() if line_entry: # We don't need to run 'process status' like Driver.cpp # Since we open the file and show the source line. r = driver.interpret_command('thread list') lldb_view_send(stdout_msg(r[0].GetOutput())) lldb_view_send(stderr_msg(r[0].GetError())) r = driver.interpret_command('frame info') lldb_view_send(stdout_msg(r[0].GetOutput())) lldb_view_send(stderr_msg(r[0].GetError())) filespec = line_entry.GetFileSpec() else: # Give us some assembly to check the crash/stop r = driver.interpret_command('process status') lldb_view_send(stdout_msg(r[0].GetOutput())) lldb_view_send(stderr_msg(r[0].GetError())) if not line_entry: # Get ALL the SBFrames t = process.GetSelectedThread() n = t.GetNumFrames() for i in xrange(0, n): f = t.GetFrameAtIndex(i) if f: line_entry = f.GetLineEntry() if line_entry and line_entry.GetFileSpec(): filespec = line_entry.GetFileSpec() if filespec: filename = filespec.GetDirectory() + '/' + filespec.GetFilename() # Maybe we don't need to focus the first group. The user knows # what he/she wants. def to_ui_thread(): window_ref().focus_group(0) v = window_ref().open_file(filename) lldb_view = get_lldb_view_for(v) if lldb_view is None: lldb_view = LLDBCodeView(v, driver) # TODO: Maybe bring the view to the front? sublime.set_timeout(to_ui_thread, 0) else: # TODO: If we don't have a filespec, we can try to disassemble # around the thread's PC. sublime.set_timeout(lambda: window_ref().run_command('lldb_disassemble_frame', {'thread': process.GetSelectedThread()}), 0)
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 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()