diff options
Diffstat (limited to 'source/Interpreter/CommandInterpreter.cpp')
-rw-r--r-- | source/Interpreter/CommandInterpreter.cpp | 337 |
1 files changed, 260 insertions, 77 deletions
diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp index 56c8f8c..176a1fc 100644 --- a/source/Interpreter/CommandInterpreter.cpp +++ b/source/Interpreter/CommandInterpreter.cpp @@ -49,7 +49,9 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Core/Timer.h" +#ifndef LLDB_DISABLE_LIBEDIT #include "lldb/Host/Editline.h" +#endif #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" @@ -117,7 +119,11 @@ CommandInterpreter::CommandInterpreter m_comment_char ('#'), m_batch_command_mode (false), m_truncation_warning(eNoTruncation), - m_command_source_depth (0) + m_command_source_depth (0), + m_num_errors(0), + m_quit_requested(false), + m_stopped_for_crash(false) + { debugger.SetScriptLanguage (script_language); SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit"); @@ -333,7 +339,11 @@ CommandInterpreter::Initialize () #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp); #else - ProcessAliasOptionsArgs (cmd_obj_sp, "--shell=" LLDB_DEFAULT_SHELL " --", alias_arguments_vector_sp); + std::string shell_option; + shell_option.append("--shell="); + shell_option.append(HostInfo::GetDefaultShell().GetPath()); + shell_option.append(" --"); + ProcessAliasOptionsArgs (cmd_obj_sp, shell_option.c_str(), alias_arguments_vector_sp); #endif AddAlias ("r", cmd_obj_sp); AddAlias ("run", cmd_obj_sp); @@ -414,6 +424,7 @@ CommandInterpreter::LoadCommandDictionary () m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this)); const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"}, + {"^/([^/]+)/$", "breakpoint set --source-pattern-regexp '%1'"}, {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"}, {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"}, {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"}, @@ -431,7 +442,8 @@ CommandInterpreter::LoadCommandDictionary () "_regexp-break [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", 2, CommandCompletions::eSymbolCompletion | - CommandCompletions::eSourceFileCompletion)); + CommandCompletions::eSourceFileCompletion, + false)); if (break_regex_cmd_ap.get()) { @@ -458,7 +470,8 @@ CommandInterpreter::LoadCommandDictionary () "_regexp-tbreak [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", 2, CommandCompletions::eSymbolCompletion | - CommandCompletions::eSourceFileCompletion)); + CommandCompletions::eSourceFileCompletion, + false)); if (tbreak_regex_cmd_ap.get()) { @@ -469,6 +482,8 @@ CommandInterpreter::LoadCommandDictionary () char buffer[1024]; int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o"); assert (num_printed < 1024); + // Quiet unused variable warning for release builds. + (void) num_printed; success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer); if (!success) break; @@ -487,7 +502,9 @@ CommandInterpreter::LoadCommandDictionary () "_regexp-attach", "Attach to a process id if in decimal, otherwise treat the argument as a process name to attach to.", "_regexp-attach [<pid>]\n_regexp-attach [<process-name>]", - 2)); + 2, + 0, + false)); if (attach_regex_cmd_ap.get()) { if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "process attach --pid %1") && @@ -504,7 +521,10 @@ CommandInterpreter::LoadCommandDictionary () down_regex_cmd_ap(new CommandObjectRegexCommand (*this, "_regexp-down", "Go down \"n\" frames in the stack (1 frame by default).", - "_regexp-down [n]", 2)); + "_regexp-down [n]", + 2, + 0, + false)); if (down_regex_cmd_ap.get()) { if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") && @@ -519,7 +539,10 @@ CommandInterpreter::LoadCommandDictionary () up_regex_cmd_ap(new CommandObjectRegexCommand (*this, "_regexp-up", "Go up \"n\" frames in the stack (1 frame by default).", - "_regexp-up [n]", 2)); + "_regexp-up [n]", + 2, + 0, + false)); if (up_regex_cmd_ap.get()) { if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") && @@ -534,7 +557,10 @@ CommandInterpreter::LoadCommandDictionary () display_regex_cmd_ap(new CommandObjectRegexCommand (*this, "_regexp-display", "Add an expression evaluation stop-hook.", - "_regexp-display expression", 2)); + "_regexp-display expression", + 2, + 0, + false)); if (display_regex_cmd_ap.get()) { if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\"")) @@ -548,7 +574,10 @@ CommandInterpreter::LoadCommandDictionary () undisplay_regex_cmd_ap(new CommandObjectRegexCommand (*this, "_regexp-undisplay", "Remove an expression evaluation stop-hook.", - "_regexp-undisplay stop-hook-number", 2)); + "_regexp-undisplay stop-hook-number", + 2, + 0, + false)); if (undisplay_regex_cmd_ap.get()) { if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1")) @@ -562,7 +591,10 @@ CommandInterpreter::LoadCommandDictionary () connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand (*this, "gdb-remote", "Connect to a remote GDB server. If no hostname is provided, localhost is assumed.", - "gdb-remote [<hostname>:]<portnum>", 2)); + "gdb-remote [<hostname>:]<portnum>", + 2, + 0, + false)); if (connect_gdb_remote_cmd_ap.get()) { if (connect_gdb_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin gdb-remote connect://%1") && @@ -577,7 +609,10 @@ CommandInterpreter::LoadCommandDictionary () connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand (*this, "kdp-remote", "Connect to a remote KDP server. udp port 41139 is the default port number.", - "kdp-remote <hostname>[:<portnum>]", 2)); + "kdp-remote <hostname>[:<portnum>]", + 2, + 0, + false)); if (connect_kdp_remote_cmd_ap.get()) { if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") && @@ -590,9 +625,12 @@ CommandInterpreter::LoadCommandDictionary () std::unique_ptr<CommandObjectRegexCommand> bt_regex_cmd_ap(new CommandObjectRegexCommand (*this, - "_regexp-bt", - "Show a backtrace. An optional argument is accepted; if that argument is a number, it specifies the number of frames to display. If that argument is 'all', full backtraces of all threads are displayed.", - "bt [<digit>|all]", 2)); + "_regexp-bt", + "Show a backtrace. An optional argument is accepted; if that argument is a number, it specifies the number of frames to display. If that argument is 'all', full backtraces of all threads are displayed.", + "bt [<digit>|all]", + 2, + 0, + false)); if (bt_regex_cmd_ap.get()) { // accept but don't document "bt -c <number>" -- before bt was a regex command if you wanted to backtrace @@ -614,7 +652,8 @@ CommandInterpreter::LoadCommandDictionary () "Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands.", "_regexp-list [<line>]\n_regexp-list [<file>:<line>]\n_regexp-list [<file>:<line>]", 2, - CommandCompletions::eSourceFileCompletion)); + CommandCompletions::eSourceFileCompletion, + false)); if (list_regex_cmd_ap.get()) { if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "source list --line %1") && @@ -634,7 +673,10 @@ CommandInterpreter::LoadCommandDictionary () env_regex_cmd_ap(new CommandObjectRegexCommand (*this, "_regexp-env", "Implements a shortcut to viewing and setting environment variables.", - "_regexp-env\n_regexp-env FOO=BAR", 2)); + "_regexp-env\n_regexp-env FOO=BAR", + 2, + 0, + false)); if (env_regex_cmd_ap.get()) { if (env_regex_cmd_ap->AddRegexCommand("^$", "settings show target.env-vars") && @@ -652,7 +694,10 @@ CommandInterpreter::LoadCommandDictionary () "_regexp-jump [<line>]\n" "_regexp-jump [<+-lineoffset>]\n" "_regexp-jump [<file>:<line>]\n" - "_regexp-jump [*<addr>]\n", 2)); + "_regexp-jump [*<addr>]\n", + 2, + 0, + false)); if (jump_regex_cmd_ap.get()) { if (jump_regex_cmd_ap->AddRegexCommand("^\\*(.*)$", "thread jump --addr %1") && @@ -1043,6 +1088,22 @@ CommandInterpreter::RemoveAlias (const char *alias_name) } return false; } + +bool +CommandInterpreter::RemoveCommand (const char *cmd) +{ + auto pos = m_command_dict.find(cmd); + if (pos != m_command_dict.end()) + { + if (pos->second->IsRemovable()) + { + // Only regular expression objects or python commands are removable + m_command_dict.erase(pos); + return true; + } + } + return false; +} bool CommandInterpreter::RemoveUser (const char *alias_name) { @@ -1448,7 +1509,7 @@ CommandInterpreter::PreprocessCommand (std::string &command) // Get a dummy target to allow for calculator mode while processing backticks. // This also helps break the infinite loop caused when target is null. if (!target) - target = Host::GetDummyTarget(GetDebugger()).get(); + target = m_debugger.GetDummyTarget(); if (target) { ValueObjectSP expr_result_valobj_sp; @@ -1462,13 +1523,15 @@ CommandInterpreter::PreprocessCommand (std::string &command) options.SetTimeoutUsec(0); ExpressionResults expr_result = target->EvaluateExpression (expr_str.c_str(), - exe_ctx.GetFramePtr(), - expr_result_valobj_sp, - options); + exe_ctx.GetFramePtr(), + expr_result_valobj_sp, + options); if (expr_result == eExpressionCompleted) { Scalar scalar; + if (expr_result_valobj_sp) + expr_result_valobj_sp = expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable(expr_result_valobj_sp->GetDynamicValueType(), true); if (expr_result_valobj_sp->ResolveValue (scalar)) { command.erase (start_backtick, end_backtick - start_backtick + 1); @@ -2415,13 +2478,14 @@ CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result) if (init_file.Exists()) { const bool saved_batch = SetBatchCommandMode (true); + CommandInterpreterRunOptions options; + options.SetSilent (true); + options.SetStopOnError (false); + options.SetStopOnContinue (true); + HandleCommandsFromFile (init_file, nullptr, // Execution context - eLazyBoolYes, // Stop on continue - eLazyBoolNo, // Stop on error - eLazyBoolNo, // Don't echo commands - eLazyBoolNo, // Don't print command output - eLazyBoolNo, // Don't add the commands that are sourced into the history buffer + options, result); SetBatchCommandMode (saved_batch); } @@ -2451,12 +2515,8 @@ CommandInterpreter::GetPlatform (bool prefer_target_platform) void CommandInterpreter::HandleCommands (const StringList &commands, - ExecutionContext *override_context, - bool stop_on_continue, - bool stop_on_error, - bool echo_commands, - bool print_results, - LazyBool add_to_history, + ExecutionContext *override_context, + CommandInterpreterRunOptions &options, CommandReturnObject &result) { size_t num_lines = commands.GetSize(); @@ -2472,7 +2532,7 @@ CommandInterpreter::HandleCommands (const StringList &commands, if (override_context != nullptr) UpdateExecutionContext (override_context); - if (!stop_on_continue) + if (!options.GetStopOnContinue()) { m_debugger.SetAsyncExecution (false); } @@ -2483,7 +2543,7 @@ CommandInterpreter::HandleCommands (const StringList &commands, if (cmd[0] == '\0') continue; - if (echo_commands) + if (options.GetEchoCommands()) { result.AppendMessageWithFormat ("%s %s\n", m_debugger.GetPrompt(), @@ -2496,16 +2556,16 @@ CommandInterpreter::HandleCommands (const StringList &commands, // We might call into a regex or alias command, in which case the add_to_history will get lost. This // m_command_source_depth dingus is the way we turn off adding to the history in that case, so set it up here. - if (!add_to_history) + if (!options.GetAddToHistory()) m_command_source_depth++; - bool success = HandleCommand(cmd, add_to_history, tmp_result, + bool success = HandleCommand(cmd, options.m_add_to_history, tmp_result, nullptr, /* override_context */ true, /* repeat_on_empty_command */ override_context != nullptr /* no_context_switching */); - if (!add_to_history) + if (!options.GetAddToHistory()) m_command_source_depth--; - if (print_results) + if (options.GetPrintResults()) { if (tmp_result.Succeeded()) result.AppendMessageWithFormat("%s", tmp_result.GetOutputData()); @@ -2516,7 +2576,7 @@ CommandInterpreter::HandleCommands (const StringList &commands, const char *error_msg = tmp_result.GetErrorData(); if (error_msg == nullptr || error_msg[0] == '\0') error_msg = "<unknown error>.\n"; - if (stop_on_error) + if (options.GetStopOnError()) { result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' failed with %s", (uint64_t)idx, cmd, error_msg); @@ -2524,7 +2584,7 @@ CommandInterpreter::HandleCommands (const StringList &commands, m_debugger.SetAsyncExecution (old_async_execution); return; } - else if (print_results) + else if (options.GetPrintResults()) { result.AppendMessageWithFormat ("Command #%" PRIu64 " '%s' failed with %s", (uint64_t)idx + 1, @@ -2545,7 +2605,7 @@ CommandInterpreter::HandleCommands (const StringList &commands, if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult) || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult)) { - if (stop_on_continue) + if (options.GetStopOnContinue()) { // If we caused the target to proceed, and we're going to stop in that case, set the // status in our real result before returning. This is an error if the continue was not the @@ -2562,6 +2622,42 @@ CommandInterpreter::HandleCommands (const StringList &commands, return; } } + + // Also check for "stop on crash here: + bool should_stop = false; + if (tmp_result.GetDidChangeProcessState() && options.GetStopOnCrash()) + { + TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget()); + if (target_sp) + { + ProcessSP process_sp (target_sp->GetProcessSP()); + if (process_sp) + { + for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) + { + StopReason reason = thread_sp->GetStopReason(); + if (reason == eStopReasonSignal || reason == eStopReasonException || reason == eStopReasonInstrumentation) + { + should_stop = true; + break; + } + } + } + } + if (should_stop) + { + if (idx != num_lines - 1) + result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' stopped with a signal or exception.\n", + (uint64_t)idx + 1, cmd); + else + result.AppendMessageWithFormat("Command #%" PRIu64 " '%s' stopped with a signal or exception.\n", (uint64_t)idx + 1, cmd); + + result.SetStatus(tmp_result.GetStatus()); + m_debugger.SetAsyncExecution (old_async_execution); + + return; + } + } } @@ -2576,17 +2672,14 @@ enum { eHandleCommandFlagStopOnContinue = (1u << 0), eHandleCommandFlagStopOnError = (1u << 1), eHandleCommandFlagEchoCommand = (1u << 2), - eHandleCommandFlagPrintResult = (1u << 3) + eHandleCommandFlagPrintResult = (1u << 3), + eHandleCommandFlagStopOnCrash = (1u << 4) }; void CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, ExecutionContext *context, - LazyBool stop_on_continue, - LazyBool stop_on_error, - LazyBool echo_command, - LazyBool print_result, - LazyBool add_to_history, + CommandInterpreterRunOptions &options, CommandReturnObject &result) { if (cmd_file.Exists()) @@ -2602,7 +2695,7 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, uint32_t flags = 0; - if (stop_on_continue == eLazyBoolCalculate) + if (options.m_stop_on_continue == eLazyBoolCalculate) { if (m_command_source_flags.empty()) { @@ -2614,12 +2707,12 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, flags |= eHandleCommandFlagStopOnContinue; } } - else if (stop_on_continue == eLazyBoolYes) + else if (options.m_stop_on_continue == eLazyBoolYes) { flags |= eHandleCommandFlagStopOnContinue; } - if (stop_on_error == eLazyBoolCalculate) + if (options.m_stop_on_error == eLazyBoolCalculate) { if (m_command_source_flags.empty()) { @@ -2631,12 +2724,25 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, flags |= eHandleCommandFlagStopOnError; } } - else if (stop_on_error == eLazyBoolYes) + else if (options.m_stop_on_error == eLazyBoolYes) { flags |= eHandleCommandFlagStopOnError; } - if (echo_command == eLazyBoolCalculate) + if (options.GetStopOnCrash()) + { + if (m_command_source_flags.empty()) + { + // Echo command by default + flags |= eHandleCommandFlagStopOnCrash; + } + else if (m_command_source_flags.back() & eHandleCommandFlagStopOnCrash) + { + flags |= eHandleCommandFlagStopOnCrash; + } + } + + if (options.m_echo_commands == eLazyBoolCalculate) { if (m_command_source_flags.empty()) { @@ -2648,12 +2754,12 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, flags |= eHandleCommandFlagEchoCommand; } } - else if (echo_command == eLazyBoolYes) + else if (options.m_echo_commands == eLazyBoolYes) { flags |= eHandleCommandFlagEchoCommand; } - if (print_result == eLazyBoolCalculate) + if (options.m_print_results == eLazyBoolCalculate) { if (m_command_source_flags.empty()) { @@ -2665,7 +2771,7 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, flags |= eHandleCommandFlagPrintResult; } } - else if (print_result == eLazyBoolYes) + else if (options.m_print_results == eLazyBoolYes) { flags |= eHandleCommandFlagPrintResult; } @@ -2680,18 +2786,21 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, lldb::StreamFileSP empty_stream_sp; m_command_source_flags.push_back(flags); IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, + IOHandler::Type::CommandInterpreter, input_file_sp, empty_stream_sp, // Pass in an empty stream so we inherit the top input reader output stream empty_stream_sp, // Pass in an empty stream so we inherit the top input reader error stream flags, nullptr, // Pass in NULL for "editline_name" so no history is saved, or written debugger.GetPrompt(), + NULL, false, // Not multi-line + debugger.GetUseColor(), 0, *this)); const bool old_async_execution = debugger.GetAsyncExecution(); - // Set synchronous execution if we not stopping when we continue + // Set synchronous execution if we are not stopping on continue if ((flags & eHandleCommandFlagStopOnContinue) == 0) debugger.SetAsyncExecution (false); @@ -2715,7 +2824,7 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, else { result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n", - cmd_file.GetFilename().AsCString()); + cmd_file.GetFilename().AsCString("<Unknown>")); result.SetStatus (eReturnStatusFailed); return; } @@ -3056,14 +3165,46 @@ CommandInterpreter::IOHandlerInputComplete (IOHandler &io_handler, std::string & break; case eReturnStatusFailed: + m_num_errors++; if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError)) io_handler.SetIsDone(true); break; case eReturnStatusQuit: + m_quit_requested = true; io_handler.SetIsDone(true); break; } + + // Finally, if we're going to stop on crash, check that here: + if (!m_quit_requested + && result.GetDidChangeProcessState() + && io_handler.GetFlags().Test(eHandleCommandFlagStopOnCrash)) + { + bool should_stop = false; + TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget()); + if (target_sp) + { + ProcessSP process_sp (target_sp->GetProcessSP()); + if (process_sp) + { + for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) + { + StopReason reason = thread_sp->GetStopReason(); + if (reason == eStopReasonSignal || reason == eStopReasonException || reason == eStopReasonInstrumentation) + { + should_stop = true; + break; + } + } + } + } + if (should_stop) + { + io_handler.SetIsDone(true); + m_stopped_for_crash = true; + } + } } bool @@ -3092,9 +3233,12 @@ CommandInterpreter::GetLLDBCommandsFromIOHandler (const char *prompt, { Debugger &debugger = GetDebugger(); IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, + IOHandler::Type::CommandList, "lldb", // Name of input reader for history prompt, // Prompt + NULL, // Continuation prompt true, // Get multiple lines + debugger.GetUseColor(), 0, // Don't show line numbers delegate)); // IOHandlerDelegate @@ -3118,9 +3262,12 @@ CommandInterpreter::GetPythonCommandsFromIOHandler (const char *prompt, { Debugger &debugger = GetDebugger(); IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, + IOHandler::Type::PythonCode, "lldb-python", // Name of input reader for history prompt, // Prompt + NULL, // Continuation prompt true, // Get multiple lines + debugger.GetUseColor(), 0, // Don't show line numbers delegate)); // IOHandlerDelegate @@ -3141,28 +3288,64 @@ CommandInterpreter::IsActive () return m_debugger.IsTopIOHandler (m_command_io_handler_sp); } -void -CommandInterpreter::RunCommandInterpreter(bool auto_handle_events, - bool spawn_thread) +lldb::IOHandlerSP +CommandInterpreter::GetIOHandler(bool force_create, CommandInterpreterRunOptions *options) { - // Only get one line at a time - const bool multiple_lines = false; - // Always re-create the IOHandlerEditline in case the input // changed. The old instance might have had a non-interactive // input and now it does or vice versa. - m_command_io_handler_sp.reset(new IOHandlerEditline (m_debugger, - m_debugger.GetInputFile(), - m_debugger.GetOutputFile(), - m_debugger.GetErrorFile(), - eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult, - "lldb", - m_debugger.GetPrompt(), - multiple_lines, - 0, // Don't show line numbers - *this)); - - m_debugger.PushIOHandler(m_command_io_handler_sp); + if (force_create || !m_command_io_handler_sp) + { + // Always re-create the IOHandlerEditline in case the input + // changed. The old instance might have had a non-interactive + // input and now it does or vice versa. + uint32_t flags = 0; + + if (options) + { + if (options->m_stop_on_continue == eLazyBoolYes) + flags |= eHandleCommandFlagStopOnContinue; + if (options->m_stop_on_error == eLazyBoolYes) + flags |= eHandleCommandFlagStopOnError; + if (options->m_stop_on_crash == eLazyBoolYes) + flags |= eHandleCommandFlagStopOnCrash; + if (options->m_echo_commands != eLazyBoolNo) + flags |= eHandleCommandFlagEchoCommand; + if (options->m_print_results != eLazyBoolNo) + flags |= eHandleCommandFlagPrintResult; + } + else + { + flags = eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult; + } + + m_command_io_handler_sp.reset(new IOHandlerEditline (m_debugger, + IOHandler::Type::CommandInterpreter, + m_debugger.GetInputFile(), + m_debugger.GetOutputFile(), + m_debugger.GetErrorFile(), + flags, + "lldb", + m_debugger.GetPrompt(), + NULL, // Continuation prompt + false, // Don't enable multiple line input, just single line commands + m_debugger.GetUseColor(), + 0, // Don't show line numbers + *this)); + } + return m_command_io_handler_sp; +} + +void +CommandInterpreter::RunCommandInterpreter(bool auto_handle_events, + bool spawn_thread, + CommandInterpreterRunOptions &options) +{ + // Always re-create the command intepreter when we run it in case + // any file handles have changed. + bool force_create = true; + m_debugger.PushIOHandler(GetIOHandler(force_create, &options)); + m_stopped_for_crash = false; if (auto_handle_events) m_debugger.StartEventHandlerThread(); @@ -3174,10 +3357,10 @@ CommandInterpreter::RunCommandInterpreter(bool auto_handle_events, else { m_debugger.ExecuteIOHanders(); - + if (auto_handle_events) m_debugger.StopEventHandlerThread(); } - + } |