void SBCommandInterpreter::ResolveCommand(const char *command_line,
                                          SBCommandReturnObject &result) {
  result.Clear();
  if (command_line && IsValid()) {
    m_opaque_ptr->ResolveCommand(command_line, result.ref());
  } else {
    result->AppendError(
        "SBCommandInterpreter or the command line is not valid");
    result->SetStatus(eReturnStatusFailed);
  }
}
示例#2
0
void
SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory (SBCommandReturnObject &result)
{
    result.Clear();
    if (m_opaque_ptr)
    {
        m_opaque_ptr->SourceInitFile (true, result.ref());
    }
    else
    {
        result->AppendError ("SBCommandInterpreter is not valid");
        result->SetStatus (eReturnStatusFailed);
    }
}
示例#3
0
void
Driver::ExecuteInitialCommands (bool before_file)
{
    size_t num_commands;
    std::vector<std::pair<bool, std::string> > *command_set;
    if (before_file)
        command_set = &(m_option_data.m_initial_commands);
    else
        command_set = &(m_option_data.m_after_file_commands);
    
    num_commands = command_set->size();
    SBCommandReturnObject result;
    bool old_async = GetDebugger().GetAsync();
    GetDebugger().SetAsync(false);
    for (size_t idx = 0; idx < num_commands; idx++)
    {
        bool is_file = (*command_set)[idx].first;
        const char *command = (*command_set)[idx].second.c_str();
        char command_string[PATH_MAX * 2];
        const bool dump_stream_only_if_no_immediate = true;
        const char *executed_command = command;
        if (is_file)
        {
            ::snprintf (command_string, sizeof(command_string), "command source -s %i '%s'", m_option_data.m_source_quietly, command);
            executed_command = command_string;
        }
        
        m_debugger.GetCommandInterpreter().HandleCommand (executed_command, result, false);
        if (!m_option_data.m_source_quietly || result.Succeeded() == false)
        {
            const size_t output_size = result.GetOutputSize();
            if (output_size > 0)
            {
                const char *cstr = result.GetOutput(dump_stream_only_if_no_immediate);
                if (cstr)
                    printf ("%s", cstr);
            }
            const size_t error_size = result.GetErrorSize();
            if (error_size > 0)
            {
                const char *cstr = result.GetError(dump_stream_only_if_no_immediate);
                if (cstr)
                    printf ("%s", cstr);
            }
        }
        
        if (result.Succeeded() == false)
        {
            const char *type = before_file ? "before file" : "after_file";
            if (is_file)
                ::fprintf(stderr, "Aborting %s command execution, command file: '%s' failed.\n", type, command);
            else
                ::fprintf(stderr, "Aborting %s command execution, command: '%s' failed.\n", type, command);
            break;
        }
        result.Clear();
    }
    GetDebugger().SetAsync(old_async);
}
示例#4
0
lldb::ReturnStatus
SBCommandInterpreter::HandleCommand (const char *command_line, SBCommandReturnObject &result, bool add_to_history)
{
    result.Clear();
    if (m_opaque_ptr)
    {
        m_opaque_ptr->HandleCommand (command_line, add_to_history, result.ref());
    }
    else
    {
        result->AppendError ("SBCommandInterpreter is not valid");
        result->SetStatus (eReturnStatusFailed);
    }
    return result.GetStatus();
}
示例#5
0
//++ ------------------------------------------------------------------------------------
// Details:	This function allows *this driver to call on another driver to perform work
//			should this driver not be able to handle the client data input.
//			SetDriverToFallThruTo() specifies the fall through to driver.
//			Check the error message if the function returns a failure.
// Type:	Overridden.
// Args:	vCmd		- (R) Command instruction to interpret.
//			vwErrMsg	- (W) Error description on command failing.
// Return:	MIstatus::success - Command succeeded.
//			MIstatus::failure - Command failed.
// Throws:	None.
//--
bool Driver::DoFallThruToAnotherDriver( const CMIUtilString & vCmd, CMIUtilString & vwErrMsg )
{
	bool bOk = MIstatus::success;
	vwErrMsg.empty();

	// ToDo: Implement do work on other driver after this driver said "Give up you try"
	// This may nto be required if the feature to 'fall through' is not required
	SBCommandReturnObject returnObj = lldb::SBCommandReturnObject();
	SBCommandInterpreter cmdIntrp = m_debugger.GetCommandInterpreter();
    const lldb::ReturnStatus cmdResult = cmdIntrp.HandleCommand( vCmd.c_str(), returnObj ); MIunused( cmdResult );
	if( returnObj.Succeeded() == false )
	{
		bOk = MIstatus::failure;
		vwErrMsg = returnObj.GetError();
	}
	
	return bOk;
}
lldb::ReturnStatus SBCommandInterpreter::HandleCommand(
    const char *command_line, SBExecutionContext &override_context,
    SBCommandReturnObject &result, bool add_to_history) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  if (log)
    log->Printf("SBCommandInterpreter(%p)::HandleCommand (command=\"%s\", "
                "SBCommandReturnObject(%p), add_to_history=%i)",
                static_cast<void *>(m_opaque_ptr), command_line,
                static_cast<void *>(result.get()), add_to_history);

  ExecutionContext ctx, *ctx_ptr;
  if (override_context.get()) {
    ctx = override_context.get()->Lock(true);
    ctx_ptr = &ctx;
  } else
    ctx_ptr = nullptr;

  result.Clear();
  if (command_line && IsValid()) {
    result.ref().SetInteractive(false);
    m_opaque_ptr->HandleCommand(command_line,
                                add_to_history ? eLazyBoolYes : eLazyBoolNo,
                                result.ref(), ctx_ptr);
  } else {
    result->AppendError(
        "SBCommandInterpreter or the command line is not valid");
    result->SetStatus(eReturnStatusFailed);
  }

  // We need to get the value again, in case the command disabled the log!
  log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API);
  if (log) {
    SBStream sstr;
    result.GetDescription(sstr);
    log->Printf("SBCommandInterpreter(%p)::HandleCommand (command=\"%s\", "
                "SBCommandReturnObject(%p): %s, add_to_history=%i) => %i",
                static_cast<void *>(m_opaque_ptr), command_line,
                static_cast<void *>(result.get()), sstr.GetData(),
                add_to_history, result.GetStatus());
  }

  return result.GetStatus();
}
示例#7
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;
}
void SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory(
    SBCommandReturnObject &result) {
  result.Clear();
  if (IsValid()) {
    TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
    std::unique_lock<std::recursive_mutex> lock;
    if (target_sp)
      lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
    m_opaque_ptr->SourceInitFile(true, result.ref());
  } else {
    result->AppendError("SBCommandInterpreter is not valid");
    result->SetStatus(eReturnStatusFailed);
  }
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  if (log)
    log->Printf(
        "SBCommandInterpreter(%p)::SourceInitFileInCurrentWorkingDirectory "
        "(&SBCommandReturnObject(%p))",
        static_cast<void *>(m_opaque_ptr), static_cast<void *>(result.get()));
}
示例#9
0
void
SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory (SBCommandReturnObject &result)
{
    result.Clear();
    if (m_opaque_ptr)
    {
        TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
        Mutex::Locker api_locker;
        if (target_sp)
            api_locker.Lock(target_sp->GetAPIMutex());
        m_opaque_ptr->SourceInitFile (true, result.ref());
    }
    else
    {
        result->AppendError ("SBCommandInterpreter is not valid");
        result->SetStatus (eReturnStatusFailed);
    }
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    if (log)
        log->Printf ("SBCommandInterpreter(%p)::SourceInitFileInCurrentWorkingDirectory (&SBCommandReturnObject(%p))", 
                     m_opaque_ptr, result.get());
}
示例#10
0
void
SBDebugger::HandleCommand (const char *command)
{
    if (m_opaque_sp)
    {
        TargetSP target_sp (m_opaque_sp->GetSelectedTarget());
        Mutex::Locker api_locker;
        if (target_sp)
            api_locker.Lock(target_sp->GetAPIMutex());

        SBCommandInterpreter sb_interpreter(GetCommandInterpreter ());
        SBCommandReturnObject result;

        sb_interpreter.HandleCommand (command, result, false);

        if (GetErrorFileHandle() != NULL)
            result.PutError (GetErrorFileHandle());
        if (GetOutputFileHandle() != NULL)
            result.PutOutput (GetOutputFileHandle());

        if (m_opaque_sp->GetAsyncExecution() == false)
        {
            SBProcess process(GetCommandInterpreter().GetProcess ());
            ProcessSP process_sp (process.GetSP());
            if (process_sp)
            {
                EventSP event_sp;
                Listener &lldb_listener = m_opaque_sp->GetListener();
                while (lldb_listener.GetNextEventForBroadcaster (process_sp.get(), event_sp))
                {
                    SBEvent event(event_sp);
                    HandleProcessEvent (process, event, GetOutputFileHandle(), GetErrorFileHandle());
                }
            }
        }
    }
}
示例#11
0
void
SBProcess::AppendEventStateReport (const SBEvent &event, SBCommandReturnObject &result)
{
    if (m_opaque_sp)
    {
        const StateType event_state = SBProcess::GetStateFromEvent (event);
        char message[1024];
        ::snprintf (message,
                    sizeof (message),
                    "Process %d %s\n",
                    m_opaque_sp->GetID(),
                    SBDebugger::StateAsCString (event_state));

        result.AppendMessage (message);
    }
}
示例#12
0
lldb::ReturnStatus
SBCommandInterpreter::HandleCommand (const char *command_line, SBCommandReturnObject &result, bool add_to_history)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    if (log)
        log->Printf ("SBCommandInterpreter(%p)::HandleCommand (command=\"%s\", SBCommandReturnObject(%p), add_to_history=%i)", 
                     m_opaque_ptr, command_line, result.get(), add_to_history);

    result.Clear();
    if (command_line && m_opaque_ptr)
    {
        TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
        Mutex::Locker api_locker;
        if (target_sp)
            api_locker.Lock(target_sp->GetAPIMutex());
        m_opaque_ptr->HandleCommand (command_line, add_to_history ? eLazyBoolYes : eLazyBoolNo, result.ref());
    }
    else
    {
        result->AppendError ("SBCommandInterpreter or the command line is not valid");
        result->SetStatus (eReturnStatusFailed);
    }

    // We need to get the value again, in case the command disabled the log!
    log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
    if (log)
    {
        SBStream sstr;
        result.GetDescription (sstr);
        log->Printf ("SBCommandInterpreter(%p)::HandleCommand (command=\"%s\", SBCommandReturnObject(%p): %s, add_to_history=%i) => %i", 
                     m_opaque_ptr, command_line, result.get(), sstr.GetData(), add_to_history, result.GetStatus());
    }

    return result.GetStatus();
}
示例#13
0
void
Driver::MainLoop ()
{
    if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
    {
        g_old_stdin_termios_is_valid = true;
        atexit (reset_stdin_termios);
    }

    ::setbuf (stdin, NULL);
    ::setbuf (stdout, NULL);

    m_debugger.SetErrorFileHandle (stderr, false);
    m_debugger.SetOutputFileHandle (stdout, false);
    m_debugger.SetInputFileHandle (stdin, false); // Don't take ownership of STDIN yet...

    m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);

    struct winsize window_size;
    if (isatty (STDIN_FILENO)
        && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
    {
        if (window_size.ws_col > 0)
            m_debugger.SetTerminalWidth (window_size.ws_col);
    }

    SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
    
    // Before we handle any options from the command line, we parse the
    // .lldbinit file in the user's home directory.
    SBCommandReturnObject result;
    sb_interpreter.SourceInitFileInHomeDirectory(result);
    if (GetDebugMode())
    {
        result.PutError (m_debugger.GetErrorFileHandle());
        result.PutOutput (m_debugger.GetOutputFileHandle());
    }

    // Now we handle options we got from the command line
    SBStream commands_stream;
    
    // First source in the commands specified to be run before the file arguments are processed.
    WriteCommandsForSourcing(eCommandPlacementBeforeFile, commands_stream);
        
    const size_t num_args = m_option_data.m_args.size();
    if (num_args > 0)
    {
        char arch_name[64];
        if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
            commands_stream.Printf("target create --arch=%s %s", arch_name, EscapeString(m_option_data.m_args[0]).c_str());
        else
            commands_stream.Printf("target create %s", EscapeString(m_option_data.m_args[0]).c_str());

        if (!m_option_data.m_core_file.empty())
        {
            commands_stream.Printf(" --core %s", EscapeString(m_option_data.m_core_file).c_str());
        }
        commands_stream.Printf("\n");
        
        if (num_args > 1)
        {
            commands_stream.Printf ("settings set -- target.run-args ");
            for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
                commands_stream.Printf(" %s", EscapeString(m_option_data.m_args[arg_idx]).c_str());
            commands_stream.Printf("\n");
        }
    }
    else if (!m_option_data.m_core_file.empty())
    {
        commands_stream.Printf("target create --core %s\n", EscapeString(m_option_data.m_core_file).c_str());
    }
    else if (!m_option_data.m_process_name.empty())
    {
        commands_stream.Printf ("process attach --name %s", EscapeString(m_option_data.m_process_name).c_str());
        
        if (m_option_data.m_wait_for)
            commands_stream.Printf(" --waitfor");

        commands_stream.Printf("\n");

    }
    else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid)
    {
        commands_stream.Printf ("process attach --pid %" PRIu64 "\n", m_option_data.m_process_pid);
    }

    WriteCommandsForSourcing(eCommandPlacementAfterFile, commands_stream);
    
    if (GetDebugMode())
    {
        result.PutError(m_debugger.GetErrorFileHandle());
        result.PutOutput(m_debugger.GetOutputFileHandle());
    }
    
    bool handle_events = true;
    bool spawn_thread = false;

    if (m_option_data.m_repl)
    {
        const char *repl_options = NULL;
        if (!m_option_data.m_repl_options.empty())
            repl_options = m_option_data.m_repl_options.c_str();
        SBError error (m_debugger.RunREPL(m_option_data.m_repl_lang, repl_options));
        if (error.Fail())
        {
            const char *error_cstr = error.GetCString();
            if (error_cstr && error_cstr[0])
                fprintf (stderr, "error: %s\n", error_cstr);
            else
                fprintf (stderr, "error: %u\n", error.GetError());
        }
    }
    else
    {
        // Check if we have any data in the commands stream, and if so, save it to a temp file
        // so we can then run the command interpreter using the file contents.
        const char *commands_data = commands_stream.GetData();
        const size_t commands_size = commands_stream.GetSize();

        // The command file might have requested that we quit, this variable will track that.
        bool quit_requested = false;
        bool stopped_for_crash = false;
        if (commands_data && commands_size)
        {
            int initial_commands_fds[2];
            bool success = true;
            FILE *commands_file = PrepareCommandsForSourcing (commands_data, commands_size, initial_commands_fds);
            if (commands_file)
            {
                m_debugger.SetInputFileHandle (commands_file, true);

                // Set the debugger into Sync mode when running the command file.  Otherwise command files
                // that run the target won't run in a sensible way.
                bool old_async = m_debugger.GetAsync();
                m_debugger.SetAsync(false);
                int num_errors;
                
                SBCommandInterpreterRunOptions options;
                options.SetStopOnError (true);
                if (m_option_data.m_batch)
                    options.SetStopOnCrash (true);

                m_debugger.RunCommandInterpreter(handle_events,
                                                 spawn_thread,
                                                 options,
                                                 num_errors,
                                                 quit_requested,
                                                 stopped_for_crash);

                if (m_option_data.m_batch && stopped_for_crash && !m_option_data.m_after_crash_commands.empty())
                {
                    int crash_command_fds[2];
                    SBStream crash_commands_stream;
                    WriteCommandsForSourcing (eCommandPlacementAfterCrash, crash_commands_stream);
                    const char *crash_commands_data = crash_commands_stream.GetData();
                    const size_t crash_commands_size = crash_commands_stream.GetSize();
                    commands_file  = PrepareCommandsForSourcing (crash_commands_data, crash_commands_size, crash_command_fds);
                    if (commands_file)
                    {
                        bool local_quit_requested;
                        bool local_stopped_for_crash;
                        m_debugger.SetInputFileHandle (commands_file, true);

                        m_debugger.RunCommandInterpreter(handle_events,
                                                         spawn_thread,
                                                         options,
                                                         num_errors,
                                                         local_quit_requested,
                                                         local_stopped_for_crash);
                        if (local_quit_requested)
                            quit_requested = true;

                    }
                }
                m_debugger.SetAsync(old_async);
            }
            else
                success = false;

            // Close any pipes that we still have ownership of
            CleanupAfterCommandSourcing(initial_commands_fds);

            // Something went wrong with command pipe
            if (!success)
            {
                exit(1);
            }

        }

        // Now set the input file handle to STDIN and run the command
        // interpreter again in interactive mode and let the debugger
        // take ownership of stdin

        bool go_interactive = true;
        if (quit_requested)
            go_interactive = false;
        else if (m_option_data.m_batch && !stopped_for_crash)
            go_interactive = false;

        if (go_interactive)
        {
            m_debugger.SetInputFileHandle (stdin, true);
            m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
        }
    }
    
    reset_stdin_termios();
    fclose (stdin);
    
    SBDebugger::Destroy (m_debugger);
}
示例#14
0
void
Driver::MainLoop ()
{
    if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
    {
        g_old_stdin_termios_is_valid = true;
        atexit (reset_stdin_termios);
    }

    ::setbuf (stdin, NULL);
    ::setbuf (stdout, NULL);

    m_debugger.SetErrorFileHandle (stderr, false);
    m_debugger.SetOutputFileHandle (stdout, false);
    m_debugger.SetInputFileHandle (stdin, true);
    
    m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);

    struct winsize window_size;
    if (isatty (STDIN_FILENO)
        && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
    {
        if (window_size.ws_col > 0)
            m_debugger.SetTerminalWidth (window_size.ws_col);
    }

    SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
    
    // Before we handle any options from the command line, we parse the
    // .lldbinit file in the user's home directory.
    SBCommandReturnObject result;
    sb_interpreter.SourceInitFileInHomeDirectory(result);
    if (GetDebugMode())
    {
        result.PutError (m_debugger.GetErrorFileHandle());
        result.PutOutput (m_debugger.GetOutputFileHandle());
    }

    // Now we handle options we got from the command line
    // First source in the commands specified to be run before the file arguments are processed.
    ExecuteInitialCommands(true);
    
    // Was there a core file specified?
    std::string core_file_spec("");
    if (!m_option_data.m_core_file.empty())
        core_file_spec.append("--core ").append(m_option_data.m_core_file);
    
    char command_string[PATH_MAX * 2];
    const size_t num_args = m_option_data.m_args.size();
    if (num_args > 0)
    {
        char arch_name[64];
        if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
            ::snprintf (command_string,
                        sizeof (command_string),
                        "target create --arch=%s %s \"%s\"",
                        arch_name,
                        core_file_spec.c_str(),
                        m_option_data.m_args[0].c_str());
        else
            ::snprintf (command_string,
                        sizeof(command_string),
                        "target create %s \"%s\"",
                        core_file_spec.c_str(),
                        m_option_data.m_args[0].c_str());
        
        m_debugger.HandleCommand (command_string);
        
        if (num_args > 1)
        {
            m_debugger.HandleCommand ("settings clear target.run-args");
            char arg_cstr[1024];
            for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
            {
                ::snprintf (arg_cstr,
                            sizeof(arg_cstr),
                            "settings append target.run-args \"%s\"",
                            m_option_data.m_args[arg_idx].c_str());
                m_debugger.HandleCommand (arg_cstr);
            }
        }
    }
    else if (!core_file_spec.empty())
    {
        ::snprintf (command_string,
                    sizeof(command_string),
                    "target create %s",
                    core_file_spec.c_str());
        m_debugger.HandleCommand (command_string);;
    }
    else if (!m_option_data.m_process_name.empty())
    {
        ::snprintf (command_string, 
                    sizeof(command_string), 
                    "process attach --name '%s'%s", 
                    m_option_data.m_process_name.c_str(), 
                    m_option_data.m_wait_for ? " --waitfor" : "");
        m_debugger.HandleCommand (command_string);
    }
    else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid)
    {
        ::snprintf (command_string, 
                    sizeof(command_string), 
                    "process attach --pid %" PRIu64, 
                    m_option_data.m_process_pid);
        m_debugger.HandleCommand (command_string);
    }

    ExecuteInitialCommands(false);

    // Now that all option parsing is done, we try and parse the .lldbinit
    // file in the current working directory
    sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
    if (GetDebugMode())
    {
        result.PutError(m_debugger.GetErrorFileHandle());
        result.PutOutput(m_debugger.GetOutputFileHandle());
    }
    
    bool handle_events = true;
    bool spawn_thread = false;
    m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
    
    reset_stdin_termios();
    fclose (stdin);
    
    SBDebugger::Destroy (m_debugger);
}
示例#15
0
文件: Driver.cpp 项目: chee-z/lldb
void
Driver::MainLoop ()
{
    if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
    {
        g_old_stdin_termios_is_valid = true;
        atexit (reset_stdin_termios);
    }

    ::setbuf (stdin, NULL);
    ::setbuf (stdout, NULL);

    m_debugger.SetErrorFileHandle (stderr, false);
    m_debugger.SetOutputFileHandle (stdout, false);
    m_debugger.SetInputFileHandle (stdin, false); // Don't take ownership of STDIN yet...

    m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);

    struct winsize window_size;
    if (isatty (STDIN_FILENO)
        && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
    {
        if (window_size.ws_col > 0)
            m_debugger.SetTerminalWidth (window_size.ws_col);
    }

    SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
    
    // Before we handle any options from the command line, we parse the
    // .lldbinit file in the user's home directory.
    SBCommandReturnObject result;
    sb_interpreter.SourceInitFileInHomeDirectory(result);
    if (GetDebugMode())
    {
        result.PutError (m_debugger.GetErrorFileHandle());
        result.PutOutput (m_debugger.GetOutputFileHandle());
    }

    // Now we handle options we got from the command line
    SBStream commands_stream;
    
    // First source in the commands specified to be run before the file arguments are processed.
    WriteInitialCommands(true, commands_stream);
        
    const size_t num_args = m_option_data.m_args.size();
    if (num_args > 0)
    {
        char arch_name[64];
        if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
            commands_stream.Printf("target create --arch=%s \"%s\"", arch_name, m_option_data.m_args[0].c_str());
        else
            commands_stream.Printf("target create \"%s\"", m_option_data.m_args[0].c_str());

        if (!m_option_data.m_core_file.empty())
        {
            commands_stream.Printf(" --core \"%s\"", m_option_data.m_core_file.c_str());
        }
        commands_stream.Printf("\n");
        
        if (num_args > 1)
        {
            commands_stream.Printf ("settings set -- target.run-args ");
            for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
            {
                const char *arg_cstr = m_option_data.m_args[arg_idx].c_str();
                if (strchr(arg_cstr, '"') == NULL)
                    commands_stream.Printf(" \"%s\"", arg_cstr);
                else
                    commands_stream.Printf(" '%s'", arg_cstr);
            }
            commands_stream.Printf("\n");
        }
    }
    else if (!m_option_data.m_core_file.empty())
    {
        commands_stream.Printf("target create --core \"%s\"\n", m_option_data.m_core_file.c_str());
    }
    else if (!m_option_data.m_process_name.empty())
    {
        commands_stream.Printf ("process attach --name \"%s\"", m_option_data.m_process_name.c_str());
        
        if (m_option_data.m_wait_for)
            commands_stream.Printf(" --waitfor");

        commands_stream.Printf("\n");

    }
    else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid)
    {
        commands_stream.Printf ("process attach --pid %" PRIu64 "\n", m_option_data.m_process_pid);
    }

    WriteInitialCommands(false, commands_stream);
    
    // Now that all option parsing is done, we try and parse the .lldbinit
    // file in the current working directory
    sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
    if (GetDebugMode())
    {
        result.PutError(m_debugger.GetErrorFileHandle());
        result.PutOutput(m_debugger.GetOutputFileHandle());
    }
    
    bool handle_events = true;
    bool spawn_thread = false;

    // Check if we have any data in the commands stream, and if so, save it to a temp file
    // so we can then run the command interpreter using the file contents.
    const char *commands_data = commands_stream.GetData();
    const size_t commands_size = commands_stream.GetSize();

    // The command file might have requested that we quit, this variable will track that.
    bool quit_requested = false;
    if (commands_data && commands_size)
    {
        enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE

        bool success = true;
        int fds[2] = { -1, -1 };
        int err = 0;
#ifdef _WIN32
        err = _pipe(fds, commands_size, O_BINARY);
#else
        err = pipe(fds);
#endif
        if (err == 0)
        {
            ssize_t nrwr = write(fds[WRITE], commands_data, commands_size);
            if (nrwr < 0)
            {
                fprintf(stderr, "error: write(%i, %p, %zd) failed (errno = %i) "
                                "when trying to open LLDB commands pipe\n",
                        fds[WRITE], commands_data, commands_size, errno);
                success = false;
            }
            else if (static_cast<size_t>(nrwr) == commands_size)
            {
                // Close the write end of the pipe so when we give the read end to
                // the debugger/command interpreter it will exit when it consumes all
                // of the data
#ifdef _WIN32
                _close(fds[WRITE]); fds[WRITE] = -1;
#else
                close(fds[WRITE]); fds[WRITE] = -1;
#endif
                // Now open the read file descriptor in a FILE * that we can give to
                // the debugger as an input handle
                FILE *commands_file = fdopen(fds[READ], "r");
                if (commands_file)
                {
                    fds[READ] = -1; // The FILE * 'commands_file' now owns the read descriptor
                    // Hand ownership if the FILE * over to the debugger for "commands_file".
                    m_debugger.SetInputFileHandle (commands_file, true);

                    // Set the debugger into Sync mode when running the command file.  Otherwise command files
                    // that run the target won't run in a sensible way.
                    bool old_async = m_debugger.GetAsync();
                    m_debugger.SetAsync(false);
                    int num_errors;
                    
                    SBCommandInterpreterRunOptions options;
                    options.SetStopOnError (true);
                    
                    m_debugger.RunCommandInterpreter(handle_events, spawn_thread, options, num_errors, quit_requested);
                    m_debugger.SetAsync(old_async);
                }
                else
                {
                    fprintf(stderr,
                            "error: fdopen(%i, \"r\") failed (errno = %i) when "
                            "trying to open LLDB commands pipe\n",
                            fds[READ], errno);
                    success = false;
                }
            }
            else
            {
                assert(!"partial writes not handled");
                success = false;
            }
        }
        else
        {
            fprintf(stderr, "error: can't create pipe file descriptors for LLDB commands\n");
            success = false;
        }

        // Close any pipes that we still have ownership of
        if ( fds[WRITE] != -1)
        {
#ifdef _WIN32
            _close(fds[WRITE]); fds[WRITE] = -1;
#else
            close(fds[WRITE]); fds[WRITE] = -1;
#endif
            
        }

        if ( fds[READ] != -1)
        {
#ifdef _WIN32
            _close(fds[READ]); fds[READ] = -1;
#else
            close(fds[READ]); fds[READ] = -1;
#endif
        }

        // Something went wrong with command pipe
        if (!success)
        {
            exit(1);
        }

    }

    // Now set the input file handle to STDIN and run the command
    // interpreter again in interactive mode and let the debugger
    // take ownership of stdin

    if (!quit_requested)
    {
        m_debugger.SetInputFileHandle (stdin, true);
        m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
    }
    
    reset_stdin_termios();
    fclose (stdin);
    
    SBDebugger::Destroy (m_debugger);
}
示例#16
0
void Driver::Initialize()
{
    m_debugger = SBDebugger::Create(false, LogOutput, 0);
    // We want to be able to handle CTRL+D in the terminal to have it terminate
    // certain input
    m_debugger.SetCloseInputOnEOF (false);
    InitializePseudoTerminal();
 

    m_debugger.SetErrorFileHandle (stderr, false);
    m_debugger.SetOutputFileHandle (stdout, false);
    m_debugger.SetInputFileHandle (stdin, true);
 
    m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);

    InitializeEditLineIO();	

	
    SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
    m_interpreter = &sb_interpreter;

    SBListener listener(m_debugger.GetListener());
    listener.StartListeningForEventClass(m_debugger, 
                                         SBTarget::GetBroadcasterClassName(), 
                                         SBTarget::eBroadcastBitBreakpointChanged);
    if (!listener.IsValid())
        return;

    listener.StartListeningForEvents (*m_io_channel_ap,
                                        IOChannel::eBroadcastBitHasUserInput |
                                        IOChannel::eBroadcastBitUserInterrupt |
                                        IOChannel::eBroadcastBitThreadShouldExit |
                                        IOChannel::eBroadcastBitThreadDidStart |
                                        IOChannel::eBroadcastBitThreadDidExit);

    if (!m_io_channel_ap->Start ())
        return;
    
	iochannel_thread_exited = false;
	
    listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
                                        SBCommandInterpreter::eBroadcastBitQuitCommandReceived |
                                        SBCommandInterpreter::eBroadcastBitAsynchronousOutputData |
                                        SBCommandInterpreter::eBroadcastBitAsynchronousErrorData);

    // Before we handle any options from the command line, we parse the
    // .lldbinit file in the user's home directory.
    SBCommandReturnObject result;
    sb_interpreter.SourceInitFileInHomeDirectory(result);

    if (GetDebugMode())
    {
        result.PutError (m_debugger.GetErrorFileHandle());
        result.PutOutput (m_debugger.GetOutputFileHandle());
    }
	HandleCommandLine(result);

    // Now that all option parsing is done, we try and parse the .lldbinit
    // file in the current working directory
    sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
    if (GetDebugMode())	
    {
        result.PutError(m_debugger.GetErrorFileHandle());
        result.PutOutput(m_debugger.GetOutputFileHandle());
    }
	SBEvent event;
    // Make sure the IO channel is started up before we try to tell it we
    // are ready for input
    listener.WaitForEventForBroadcasterWithType (UINT32_MAX, 
                                                    *m_io_channel_ap,
                                                    IOChannel::eBroadcastBitThreadDidStart, 
                                                    event);
    
    // If we were asked to attach, then do that here:
    // I'm going to use the command string rather than directly
    // calling the API's because then I don't have to recode the
    // event handling here.
    if (!m_option_data.m_process_name.empty()
        || m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
    {
        AttachToProcess();
    }
    
    ReadyForCommand ();
}
示例#17
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;
        }
    }
}