Beispiel #1
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());
                }
            }
        }
    }
}
Beispiel #2
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);
}
Beispiel #3
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);
}
Beispiel #4
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 ();
}
Beispiel #5
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.
    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);
}