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))
Exemple #2
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 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()