Beispiel #1
0
bool
Driver::HandleIOEvent (const SBEvent &event)
{
    bool quit = false;

    const uint32_t event_type = event.GetType();

    if (event_type & IOChannel::eBroadcastBitHasUserInput)
    {
        // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
        // handling.

        const char *command_string = SBEvent::GetCStringFromEvent(event);
        if (command_string == NULL)
            command_string = "";
        SBCommandReturnObject result;
        
        // We don't want the result to bypass the OutWrite function in IOChannel, as this can result in odd
        // output orderings and problems with the prompt.
        m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true);

        if (result.GetOutputSize() > 0)
            m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), NO_ASYNC);
            
        if (result.GetErrorSize() > 0)
            m_io_channel_ap->OutWrite (result.GetError(), result.GetErrorSize(), NO_ASYNC);

        // We are done getting and running our command, we can now clear the
        // m_waiting_for_command so we can get another one.
        m_waiting_for_command = false;

        // If our editline input reader is active, it means another input reader
        // got pushed onto the input reader and caused us to become deactivated.
        // When the input reader above us gets popped, we will get re-activated
        // and our prompt will refresh in our callback
        if (m_editline_reader.IsActive())
        {
            ReadyForCommand ();
        }
    }
    else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
    {
        // This is here to handle control-c interrupts from the user.  It has not yet really been implemented.
        // TO BE DONE:  PROPERLY HANDLE CONTROL-C FROM USER
        //m_io_channel_ap->CancelInput();
        // Anything else?  Send Interrupt to process?
    }
    else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
             (event_type & IOChannel::eBroadcastBitThreadDidExit))
    {
        // If the IOChannel thread is trying to go away, then it is definitely
        // time to end the debugging session.
        quit = true;
    }

    return quit;
}
Beispiel #2
0
void
Driver::ProcessEvent(SBEvent& event)
{
    if (!event.GetBroadcaster().IsValid())
        return;

    uint32_t event_type = event.GetType();
    if (event.BroadcasterMatchesRef (*m_io_channel_ap))
    {
        if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
            (event_type & IOChannel::eBroadcastBitThreadDidExit))
        {
            SetIsDone();
            if (event_type & IOChannel::eBroadcastBitThreadDidExit)
                iochannel_thread_exited = true;
        }
        else
        {
            if (HandleIOEvent (event))
                SetIsDone();
        }
    }
    else if (SBProcess::EventIsProcessEvent (event))
    {
        HandleProcessEvent (event);
    }
    else if (SBBreakpoint::EventIsBreakpointEvent (event))
    {
        HandleBreakpointEvent (event);
    }
    else if (event.BroadcasterMatchesRef (m_interpreter->GetBroadcaster()))
    {
        // TODO: deprecate the eBroadcastBitQuitCommandReceived event
        // now that we have SBCommandInterpreter::SetCommandOverrideCallback()
        // that can take over a command
        if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
        {
            SetIsDone();
        }
        else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousErrorData)
        {
            const char *data = SBEvent::GetCStringFromEvent (event);
            m_io_channel_ap->ErrWrite (data, strlen(data), ASYNC);
        }
        else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousOutputData)
        {
            const char *data = SBEvent::GetCStringFromEvent (event);
            m_io_channel_ap->OutWrite (data, strlen(data), ASYNC);
        }
    }
}
Beispiel #3
0
void
SBDebugger::HandleProcessEvent (const SBProcess &process, const SBEvent &event, FILE *out, FILE *err)
{
    if (!process.IsValid())
        return;

    TargetSP target_sp (process.GetTarget().GetSP());
    if (!target_sp)
        return;

    const uint32_t event_type = event.GetType();
    char stdio_buffer[1024];
    size_t len;

    Mutex::Locker api_locker (target_sp->GetAPIMutex());
    
    if (event_type & (Process::eBroadcastBitSTDOUT | Process::eBroadcastBitStateChanged))
    {
        // Drain stdout when we stop just in case we have any bytes
        while ((len = process.GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
            if (out != NULL)
                ::fwrite (stdio_buffer, 1, len, out);
    }
    
    if (event_type & (Process::eBroadcastBitSTDERR | Process::eBroadcastBitStateChanged))
    {
        // Drain stderr when we stop just in case we have any bytes
        while ((len = process.GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
            if (err != NULL)
                ::fwrite (stdio_buffer, 1, len, err);
    }
    
    if (event_type & Process::eBroadcastBitStateChanged)
    {
        StateType event_state = SBProcess::GetStateFromEvent (event);
        
        if (event_state == eStateInvalid)
            return;
        
        bool is_stopped = StateIsStoppedState (event_state);
        if (!is_stopped)
            process.ReportEventState (event, out);
    }
}
Beispiel #4
0
void
IOChannel::Run ()
{
    SBListener listener("IOChannel::Run");
    std::string new_line;

    SBBroadcaster interpreter_broadcaster (m_driver->GetDebugger().GetCommandInterpreter().GetBroadcaster());
    listener.StartListeningForEvents (interpreter_broadcaster,
                                      SBCommandInterpreter::eBroadcastBitResetPrompt |
                                      SBCommandInterpreter::eBroadcastBitThreadShouldExit |
                                      SBCommandInterpreter::eBroadcastBitQuitCommandReceived);

    listener.StartListeningForEvents (*this,
                                      IOChannel::eBroadcastBitThreadShouldExit);

    listener.StartListeningForEvents (*m_driver,
                                      Driver::eBroadcastBitReadyForInput |
                                      Driver::eBroadcastBitThreadShouldExit);

    // Let anyone know that the IO channel is up and listening and ready for events
    BroadcastEventByType (eBroadcastBitThreadDidStart);
    bool done = false;
    while (!done)
    {
        SBEvent event;

        listener.WaitForEvent (UINT32_MAX, event);
        if (!event.IsValid())
            continue;

        const uint32_t event_type = event.GetType();

        if (event.GetBroadcaster().IsValid())
        {
            if (event.BroadcasterMatchesPtr (m_driver))
            {
                if (event_type & Driver::eBroadcastBitReadyForInput)
                {
                    std::string line;

                    if (CommandQueueIsEmpty())
                    {
                        if (LibeditGetInput(line) == false)
                        {
                            // EOF or some other file error occurred
                            done = true;
                            continue;
                        }
                    }
                    else
                    {
                        GetCommandFromQueue (line);
                    }

                    // TO BE DONE: FIGURE OUT WHICH COMMANDS SHOULD NOT BE REPEATED IF USER PRESSES PLAIN 'RETURN'
                    // AND TAKE CARE OF THAT HERE.

                    SBEvent line_event(IOChannel::eBroadcastBitHasUserInput,
                             line.c_str(),
                             line.size());
                    BroadcastEvent (line_event);
                }
                else if (event_type & Driver::eBroadcastBitThreadShouldExit)
                {
                    done = true;
                    break;
                }
            }
            else if (event.BroadcasterMatchesRef (interpreter_broadcaster))
            {
                switch (event_type)
                {
                case SBCommandInterpreter::eBroadcastBitResetPrompt:
                    {
                        const char *new_prompt = SBEvent::GetCStringFromEvent (event);
                        if (new_prompt)
                            g_prompt_map[m_edit_line] = new_prompt;
                    }
                    break;

                case SBCommandInterpreter::eBroadcastBitThreadShouldExit:
                case SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
                    done = true;
                    break;
                }
            }
            else if (event.BroadcasterMatchesPtr (this))
            {
                if (event_type & IOChannel::eBroadcastBitThreadShouldExit)
                {
                    done = true;
                    break;
                }
            }
        }
    }
    BroadcastEventByType (IOChannel::eBroadcastBitThreadDidExit);
    m_driver = NULL;
    m_read_thread = NULL;
}
Beispiel #5
0
// This function handles events that were broadcast by the process.
void
Driver::HandleProcessEvent (const SBEvent &event)
{
    using namespace lldb;
    const uint32_t event_type = event.GetType();

    if (event_type & SBProcess::eBroadcastBitSTDOUT)
    {
        // The process has stdout available, get it and write it out to the
        // appropriate place.
        GetProcessSTDOUT ();
    }
    else if (event_type & SBProcess::eBroadcastBitSTDERR)
    {
        // The process has stderr available, get it and write it out to the
        // appropriate place.
        GetProcessSTDERR ();
    }
    else if (event_type & SBProcess::eBroadcastBitStateChanged)
    {
        // Drain all stout and stderr so we don't see any output come after
        // we print our prompts
        GetProcessSTDOUT ();
        GetProcessSTDERR ();
        // Something changed in the process;  get the event and report the process's current status and location to
        // the user.
        StateType event_state = SBProcess::GetStateFromEvent (event);
        if (event_state == eStateInvalid)
            return;

        SBProcess process (SBProcess::GetProcessFromEvent (event));
        assert (process.IsValid());

        switch (event_state)
        {
        case eStateInvalid:
        case eStateUnloaded:
        case eStateConnected:
        case eStateAttaching:
        case eStateLaunching:
        case eStateStepping:
        case eStateDetached:
            {
                char message[1024];
                int message_len = ::snprintf (message, sizeof(message), "Process %llu %s\n", process.GetProcessID(),
                                              m_debugger.StateAsCString (event_state));
                m_io_channel_ap->OutWrite(message, message_len, ASYNC);
            }
            break;

        case eStateRunning:
            // Don't be chatty when we run...
            break;

        case eStateExited:
            {
                SBCommandReturnObject result;
                m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
                m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
                m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
            }
            break;

        case eStateStopped:
        case eStateCrashed:
        case eStateSuspended:
            // Make sure the program hasn't been auto-restarted:
            if (SBProcess::GetRestartedFromEvent (event))
            {
                // FIXME: Do we want to report this, or would that just be annoyingly chatty?
                char message[1024];
                int message_len = ::snprintf (message, sizeof(message), "Process %llu stopped and was programmatically restarted.\n",
                                              process.GetProcessID());
                m_io_channel_ap->OutWrite(message, message_len, ASYNC);
            }
            else
            {
                if (GetDebugger().GetSelectedTarget() == process.GetTarget())
                {
                    SBCommandReturnObject result;
                    UpdateSelectedThread ();
                    m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
                    m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
                    m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
                }
                else
                {
                    SBStream out_stream;
                    uint32_t target_idx = GetDebugger().GetIndexOfTarget(process.GetTarget());
                    if (target_idx != UINT32_MAX)
                        out_stream.Printf ("Target %d: (", target_idx);
                    else
                        out_stream.Printf ("Target <unknown index>: (");
                    process.GetTarget().GetDescription (out_stream, eDescriptionLevelBrief);
                    out_stream.Printf (") stopped.\n");
                    m_io_channel_ap->OutWrite (out_stream.GetData(), out_stream.GetSize(), ASYNC);
                }
            }
            break;
        }
    }
}