diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Interpreter')
27 files changed, 770 insertions, 136 deletions
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/Args.cpp b/contrib/llvm/tools/lldb/source/Interpreter/Args.cpp index 4831eaa..9393380 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/Args.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/Args.cpp @@ -685,7 +685,7 @@ Args::ParseOptions (Options &options) } } // Call the callback with the option - if (long_options_index >= 0) + if (long_options_index >= 0 && long_options[long_options_index].definition) { const OptionDefinition *def = long_options[long_options_index].definition; CommandInterpreter &interpreter = options.GetInterpreter(); @@ -829,15 +829,18 @@ Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::add options.SetTryAllThreads(true); ExpressionResults expr_result = target->EvaluateExpression(s, - exe_ctx->GetFramePtr(), - valobj_sp, - options); + exe_ctx->GetFramePtr(), + valobj_sp, + options); bool success = false; if (expr_result == eExpressionCompleted) { + if (valobj_sp) + valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable(valobj_sp->GetDynamicValueType(), true); // Get the address to watch. - addr = valobj_sp->GetValueAsUnsigned(fail_value, &success); + if (valobj_sp) + addr = valobj_sp->GetValueAsUnsigned(fail_value, &success); if (success) { if (error_ptr) @@ -966,6 +969,26 @@ Args::StringToBoolean (const char *s, bool fail_value, bool *success_ptr) return fail_value; } +char +Args::StringToChar(const char *s, char fail_value, bool *success_ptr) +{ + bool success = false; + char result = fail_value; + + if (s) + { + size_t length = strlen(s); + if (length == 1) + { + success = true; + result = s[0]; + } + } + if (success_ptr) + *success_ptr = success; + return result; +} + const char * Args::StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t &update) { diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp index 56c8f8c..176a1fc 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/contrib/llvm/tools/lldb/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(); } - + } diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp index 3fdbf99..753e720 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp @@ -49,7 +49,7 @@ CommandObject::CommandObject uint32_t flags ) : m_interpreter (interpreter), - m_cmd_name (name), + m_cmd_name (name ? name : ""), m_cmd_help_short (), m_cmd_help_long (), m_cmd_syntax (), @@ -236,19 +236,34 @@ CommandObject::CheckRequirements (CommandReturnObject &result) if ((flags & eFlagRequiresProcess) && !m_exe_ctx.HasProcessScope()) { - result.AppendError (GetInvalidProcessDescription()); + if (!m_exe_ctx.HasTargetScope()) + result.AppendError (GetInvalidTargetDescription()); + else + result.AppendError (GetInvalidProcessDescription()); return false; } if ((flags & eFlagRequiresThread) && !m_exe_ctx.HasThreadScope()) { - result.AppendError (GetInvalidThreadDescription()); + if (!m_exe_ctx.HasTargetScope()) + result.AppendError (GetInvalidTargetDescription()); + else if (!m_exe_ctx.HasProcessScope()) + result.AppendError (GetInvalidProcessDescription()); + else + result.AppendError (GetInvalidThreadDescription()); return false; } if ((flags & eFlagRequiresFrame) && !m_exe_ctx.HasFrameScope()) { - result.AppendError (GetInvalidFrameDescription()); + if (!m_exe_ctx.HasTargetScope()) + result.AppendError (GetInvalidTargetDescription()); + else if (!m_exe_ctx.HasProcessScope()) + result.AppendError (GetInvalidProcessDescription()); + else if (!m_exe_ctx.HasThreadScope()) + result.AppendError (GetInvalidThreadDescription()); + else + result.AppendError (GetInvalidFrameDescription()); return false; } @@ -733,6 +748,22 @@ BreakpointIDRangeHelpTextCallback () } static const char * +BreakpointNameHelpTextCallback () +{ + return "A name that can be added to a breakpoint when it is created, or later " + "on with the \"breakpoint name add\" command. " + "Breakpoint names can be used to specify breakpoints in all the places breakpoint ID's " + "and breakpoint ID ranges can be used. As such they provide a convenient way to group breakpoints, " + "and to operate on breakpoints you create without having to track the breakpoint number. " + "Note, the attributes you set when using a breakpoint name in a breakpoint command don't " + "adhere to the name, but instead are set individually on all the breakpoints currently tagged with that name. Future breakpoints " + "tagged with that name will not pick up the attributes previously given using that name. " + "In order to distinguish breakpoint names from breakpoint ID's and ranges, " + "names must start with a letter from a-z or A-Z and cannot contain spaces, \".\" or \"-\". " + "Also, breakpoint names can only be applied to breakpoints, not to breakpoint locations."; +} + +static const char * GDBFormatHelpTextCallback () { return "A GDB format consists of a repeat count, a format letter and a size letter. " @@ -1003,6 +1034,18 @@ CommandObject::GetArgumentDescriptionAsCString (const lldb::CommandArgumentType return nullptr; } +Target * +CommandObject::GetDummyTarget() +{ + return m_interpreter.GetDebugger().GetDummyTarget(); +} + +Target * +CommandObject::GetSelectedOrDummyTarget(bool prefer_dummy) +{ + return m_interpreter.GetDebugger().GetSelectedOrDummyTarget(prefer_dummy); +} + bool CommandObjectParsed::Execute (const char *args_string, CommandReturnObject &result) { @@ -1085,6 +1128,7 @@ CommandObject::g_arguments_data[] = { eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, { nullptr, false }, "A Boolean value: 'true' or 'false'" }, { eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, { BreakpointIDHelpTextCallback, false }, nullptr }, { eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, { BreakpointIDRangeHelpTextCallback, false }, nullptr }, + { eArgTypeBreakpointName, "breakpoint-name", CommandCompletions::eNoCompletion, { BreakpointNameHelpTextCallback, false }, nullptr }, { eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, { nullptr, false }, "Number of bytes to use." }, { eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, { nullptr, false }, "Then name of a class from the debug information in the program." }, { eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, { nullptr, false }, "A debugger command (may be multiple words), without any options or arguments." }, @@ -1103,6 +1147,7 @@ CommandObject::g_arguments_data[] = { eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a function." }, { eArgTypeFunctionOrSymbol, "function-or-symbol", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a function or symbol." }, { eArgTypeGDBFormat, "gdb-format", CommandCompletions::eNoCompletion, { GDBFormatHelpTextCallback, true }, nullptr }, + { eArgTypeHelpText, "help-text", CommandCompletions::eNoCompletion, { nullptr, false }, "Text to be used as help for some other entity in LLDB" }, { eArgTypeIndex, "index", CommandCompletions::eNoCompletion, { nullptr, false }, "An index into a list." }, { eArgTypeLanguage, "language", CommandCompletions::eNoCompletion, { LanguageTypeHelpTextCallback, true }, nullptr }, { eArgTypeLineNum, "linenum", CommandCompletions::eNoCompletion, { nullptr, false }, "Line number in a source file." }, diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectRegexCommand.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectRegexCommand.cpp index d27320d..efc7c33 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectRegexCommand.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectRegexCommand.cpp @@ -31,12 +31,14 @@ CommandObjectRegexCommand::CommandObjectRegexCommand const char *help, const char *syntax, uint32_t max_matches, - uint32_t completion_type_mask + uint32_t completion_type_mask, + bool is_removable ) : CommandObjectRaw (interpreter, name, help, syntax), m_max_matches (max_matches), m_completion_type_mask (completion_type_mask), - m_entries () + m_entries (), + m_is_removable (is_removable) { } diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupPlatform.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupPlatform.cpp index 9ffd5f0..7e5e124 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupPlatform.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupPlatform.cpp @@ -33,7 +33,7 @@ OptionGroupPlatform::CreatePlatformWithOptions (CommandInterpreter &interpreter, if (!m_platform_name.empty()) { - platform_sp = Platform::Create (m_platform_name.c_str(), error); + platform_sp = Platform::Create (ConstString(m_platform_name.c_str()), error); if (platform_sp) { if (platform_arch.IsValid() && !platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp index 125e5fb..b6c63fa 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp @@ -45,6 +45,7 @@ g_option_table[] = { LLDB_OPT_SET_1, false, "no-summary-depth", 'Y', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the depth at which omitting summary information stops (default is 1)."}, { LLDB_OPT_SET_1, false, "raw-output", 'R', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use formatting options."}, { LLDB_OPT_SET_1, false, "show-all-children", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Ignore the upper bound on the number of children to show."}, + { LLDB_OPT_SET_1, false, "validate", 'V', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Show results of type validators."}, { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } }; @@ -115,6 +116,13 @@ OptionGroupValueObjectDisplay::SetOptionValue (CommandInterpreter &interpreter, if (!success) error.SetErrorStringWithFormat("invalid synthetic-type '%s'", option_arg); break; + + case 'V': + run_validator = Args::StringToBoolean(option_arg, true, &success); + if (!success) + error.SetErrorStringWithFormat("invalid validate '%s'", option_arg); + break; + default: error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); break; @@ -137,6 +145,7 @@ OptionGroupValueObjectDisplay::OptionParsingStarting (CommandInterpreter &interp use_synth = true; be_raw = false; ignore_cap = false; + run_validator = false; Target *target = interpreter.GetExecutionContext().GetTargetPtr(); if (target != nullptr) @@ -176,7 +185,9 @@ OptionGroupValueObjectDisplay::GetAsDumpOptions (LanguageRuntimeDescriptionDispl .SetHideValue(use_objc); if (be_raw) - options.SetRawDisplay(true); + options.SetRawDisplay(); + + options.SetRunValidator(run_validator); return options; } diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValue.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValue.cpp index bc1e1c4..a08a612 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValue.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValue.cpp @@ -71,6 +71,21 @@ OptionValue::GetAsBoolean () const return nullptr; } +const OptionValueChar * +OptionValue::GetAsChar () const +{ + if (GetType () == OptionValue::eTypeChar) + return static_cast<const OptionValueChar *>(this); + return nullptr; +} + +OptionValueChar * +OptionValue::GetAsChar () +{ + if (GetType () == OptionValue::eTypeChar) + return static_cast<OptionValueChar *>(this); + return nullptr; +} OptionValueFileSpec * OptionValue::GetAsFileSpec () @@ -342,6 +357,27 @@ OptionValue::SetBooleanValue (bool new_value) return false; } +char +OptionValue::GetCharValue(char fail_value) const +{ + const OptionValueChar *option_value = GetAsChar(); + if (option_value) + return option_value->GetCurrentValue(); + return fail_value; +} + +char +OptionValue::SetCharValue(char new_value) +{ + OptionValueChar *option_value = GetAsChar(); + if (option_value) + { + option_value->SetCurrentValue(new_value); + return true; + } + return false; +} + int64_t OptionValue::GetEnumerationValue (int64_t fail_value) const { @@ -520,6 +556,8 @@ OptionValue::GetBuiltinTypeAsCString (Type t) case eTypeArgs: return "arguments"; case eTypeArray: return "array"; case eTypeBoolean: return "boolean"; + case eTypeChar: + return "char"; case eTypeDictionary: return "dictionary"; case eTypeEnum: return "enum"; case eTypeFileSpec: return "file"; @@ -547,6 +585,7 @@ OptionValue::CreateValueFromCStringForTypeMask (const char *value_cstr, uint32_t { case 1u << eTypeArch: value_sp.reset(new OptionValueArch()); break; case 1u << eTypeBoolean: value_sp.reset(new OptionValueBoolean(false)); break; + case 1u << eTypeChar: value_sp.reset(new OptionValueChar('\0')); break; case 1u << eTypeFileSpec: value_sp.reset(new OptionValueFileSpec()); break; case 1u << eTypeFormat: value_sp.reset(new OptionValueFormat(eFormatInvalid)); break; case 1u << eTypeSInt64: value_sp.reset(new OptionValueSInt64()); break; diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArch.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArch.cpp index 6d283d6..7df1492 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArch.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArch.cpp @@ -50,6 +50,7 @@ OptionValueArch::SetValueFromCString (const char *value_cstr, VarSetOperationTyp { case eVarSetOperationClear: Clear(); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -57,7 +58,10 @@ OptionValueArch::SetValueFromCString (const char *value_cstr, VarSetOperationTyp if (value_cstr && value_cstr[0]) { if (m_current_value.SetTriple (value_cstr)) + { m_value_was_set = true; + NotifyValueChanged(); + } else error.SetErrorStringWithFormat("unsupported architecture '%s'", value_cstr); } diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArray.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArray.cpp index 769aadd..c0d48c1 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArray.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArray.cpp @@ -53,6 +53,7 @@ OptionValueArray::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint break; case eTypeBoolean: + case eTypeChar: case eTypeEnum: case eTypeFileSpec: case eTypeFormat: @@ -75,6 +76,7 @@ Error OptionValueArray::SetValueFromCString (const char *value, VarSetOperationType op) { Args args(value); + NotifyValueChanged(); return SetArgs (args, op); } diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueBoolean.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueBoolean.cpp index bf153a1..71cc2af 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueBoolean.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueBoolean.cpp @@ -45,6 +45,7 @@ OptionValueBoolean::SetValueFromCString (const char *value_cstr, { case eVarSetOperationClear: Clear(); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -56,6 +57,7 @@ OptionValueBoolean::SetValueFromCString (const char *value_cstr, { m_value_was_set = true; m_current_value = value; + NotifyValueChanged(); } else { diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueChar.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueChar.cpp new file mode 100644 index 0000000..7a01353 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueChar.cpp @@ -0,0 +1,80 @@ +//===-- OptionValueChar.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Interpreter/OptionValueChar.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Stream.h" +#include "lldb/Core/StringList.h" +#include "lldb/Interpreter/Args.h" +#include "llvm/ADT/STLExtras.h" + +using namespace lldb; +using namespace lldb_private; + +void +OptionValueChar::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) +{ + if (dump_mask & eDumpOptionType) + strm.Printf ("(%s)", GetTypeAsCString ()); + + if (dump_mask & eDumpOptionValue) + { + if (dump_mask & eDumpOptionType) + strm.PutCString (" = "); + if (m_current_value != '\0') + strm.PutChar(m_current_value); + else + strm.PutCString("(null)"); + } +} + +Error +OptionValueChar::SetValueFromCString (const char *value_cstr, + VarSetOperationType op) +{ + Error error; + switch (op) + { + case eVarSetOperationClear: + Clear(); + break; + + case eVarSetOperationReplace: + case eVarSetOperationAssign: + { + bool success = false; + char char_value = Args::StringToChar(value_cstr, '\0', &success); + if (success) + { + m_current_value = char_value; + m_value_was_set = true; + } + else + error.SetErrorStringWithFormat("'%s' cannot be longer than 1 character", value_cstr); + } + break; + + default: + error = OptionValue::SetValueFromCString (value_cstr, op); + break; + } + return error; +} + +lldb::OptionValueSP +OptionValueChar::DeepCopy () const +{ + return OptionValueSP(new OptionValueChar(*this)); +} + + diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp index b560937..e5299f8 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp @@ -64,6 +64,7 @@ OptionValueDictionary::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, break; case eTypeBoolean: + case eTypeChar: case eTypeEnum: case eTypeFileSpec: case eTypeFormat: @@ -220,7 +221,10 @@ Error OptionValueDictionary::SetValueFromCString (const char *value_cstr, VarSetOperationType op) { Args args(value_cstr); - return SetArgs (args, op); + Error error = SetArgs (args, op); + if (error.Success()) + NotifyValueChanged(); + return error; } lldb::OptionValueSP diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueEnumeration.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueEnumeration.cpp index 7aceac9..dbaeb18 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueEnumeration.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueEnumeration.cpp @@ -62,6 +62,7 @@ OptionValueEnumeration::SetValueFromCString (const char *value, VarSetOperationT { case eVarSetOperationClear: Clear (); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -73,6 +74,7 @@ OptionValueEnumeration::SetValueFromCString (const char *value, VarSetOperationT if (enumerator_entry) { m_current_value = enumerator_entry->value.value; + NotifyValueChanged(); } else { diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpec.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpec.cpp index c8aaade..3f46698 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpec.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpec.cpp @@ -78,6 +78,7 @@ OptionValueFileSpec::SetValueFromCString (const char *value_cstr, { case eVarSetOperationClear: Clear (); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -100,6 +101,7 @@ OptionValueFileSpec::SetValueFromCString (const char *value_cstr, m_value_was_set = true; m_current_value.SetFile(filepath.c_str(), true); m_data_sp.reset(); + NotifyValueChanged(); } else { diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpecLIst.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpecLIst.cpp index e493c70..7150ad4 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpecLIst.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpecLIst.cpp @@ -51,6 +51,7 @@ OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperation { case eVarSetOperationClear: Clear (); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -72,6 +73,7 @@ OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperation else m_current_value.Append(file); } + NotifyValueChanged(); } } else @@ -94,6 +96,7 @@ OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperation FileSpec file (args.GetArgumentAtIndex(i), false); m_current_value.Append(file); } + NotifyValueChanged(); } else { @@ -120,6 +123,7 @@ OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperation FileSpec file (args.GetArgumentAtIndex(i), false); m_current_value.Insert (idx, file); } + NotifyValueChanged(); } } else @@ -155,6 +159,7 @@ OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperation m_current_value.Remove (j); } } + NotifyValueChanged(); } else { @@ -172,9 +177,6 @@ OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperation break; } return error; - - m_value_was_set = true; - return Error(); } lldb::OptionValueSP diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFormat.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFormat.cpp index 296dd98..d91f10b 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFormat.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFormat.cpp @@ -43,6 +43,7 @@ OptionValueFormat::SetValueFromCString (const char *value_cstr, VarSetOperationT { case eVarSetOperationClear: Clear(); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -54,6 +55,7 @@ OptionValueFormat::SetValueFromCString (const char *value_cstr, VarSetOperationT { m_value_was_set = true; m_current_value = new_format; + NotifyValueChanged(); } } break; diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValuePathMappings.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValuePathMappings.cpp index 88a0eb7..56f2ecf 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValuePathMappings.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValuePathMappings.cpp @@ -43,6 +43,7 @@ OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperation { case eVarSetOperationClear: Clear (); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -64,6 +65,7 @@ OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperation if (!m_path_mappings.Replace (a, b, idx, m_notify_changes)) m_path_mappings.Append(a, b, m_notify_changes); } + NotifyValueChanged(); } } else @@ -97,6 +99,7 @@ OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperation m_path_mappings.Append(a, b, m_notify_changes); m_value_was_set = true; } + NotifyValueChanged(); } break; @@ -121,6 +124,7 @@ OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperation ConstString b(args.GetArgumentAtIndex(i+1)); m_path_mappings.Insert (a, b, idx, m_notify_changes); } + NotifyValueChanged(); } } else @@ -156,6 +160,7 @@ OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperation m_path_mappings.Remove (j, m_notify_changes); } } + NotifyValueChanged(); } else { @@ -173,9 +178,6 @@ OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperation break; } return error; - - m_value_was_set = true; - return Error(); } lldb::OptionValueSP diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp index 0497ee1..6ec2aa5 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp @@ -81,6 +81,16 @@ OptionValueProperties::Initialize (const PropertyDefinition *defs) } void +OptionValueProperties::SetValueChangedCallback (uint32_t property_idx, + OptionValueChangedCallback callback, + void *baton) +{ + Property *property = ProtectedGetPropertyAtIndex (property_idx); + if (property) + property->SetValueChangedCallback (callback, baton); +} + +void OptionValueProperties::AppendProperty(const ConstString &name, const ConstString &desc, bool is_global, diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueRegex.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueRegex.cpp index f1ba0ed..f51cf02 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueRegex.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueRegex.cpp @@ -57,6 +57,7 @@ OptionValueRegex::SetValueFromCString (const char *value_cstr, case eVarSetOperationClear: Clear(); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -64,6 +65,7 @@ OptionValueRegex::SetValueFromCString (const char *value_cstr, if (m_regex.Compile (value_cstr, m_regex.GetCompileFlags())) { m_value_was_set = true; + NotifyValueChanged(); } else { diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueSInt64.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueSInt64.cpp index 04bf930..1827cc1 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueSInt64.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueSInt64.cpp @@ -44,6 +44,7 @@ OptionValueSInt64::SetValueFromCString (const char *value_cstr, VarSetOperationT { case eVarSetOperationClear: Clear(); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -57,6 +58,7 @@ OptionValueSInt64::SetValueFromCString (const char *value_cstr, VarSetOperationT { m_value_was_set = true; m_current_value = value; + NotifyValueChanged(); } else error.SetErrorStringWithFormat ("%" PRIi64 " is out of range, valid values must be between %" PRIi64 " and %" PRIi64 ".", diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueString.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueString.cpp index df047bd..a1b80d8 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueString.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueString.cpp @@ -94,30 +94,32 @@ OptionValueString::SetValueFromCString (const char *value_cstr, case eVarSetOperationAppend: { - std::string new_value(m_current_value); - if (value_cstr && value_cstr[0]) - { - if (m_options.Test (eOptionEncodeCharacterEscapeSequences)) + std::string new_value(m_current_value); + if (value_cstr && value_cstr[0]) { - std::string str; - Args::EncodeEscapeSequences (value_cstr, str); - new_value.append(str); + if (m_options.Test (eOptionEncodeCharacterEscapeSequences)) + { + std::string str; + Args::EncodeEscapeSequences (value_cstr, str); + new_value.append(str); + } + else + new_value.append(value_cstr); } - else - new_value.append(value_cstr); - } - if (m_validator) - { - error = m_validator(new_value.c_str(),m_validator_baton); - if (error.Fail()) - return error; - } - m_current_value.assign(new_value); + if (m_validator) + { + error = m_validator(new_value.c_str(),m_validator_baton); + if (error.Fail()) + return error; + } + m_current_value.assign(new_value); + NotifyValueChanged(); } break; case eVarSetOperationClear: Clear (); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -137,6 +139,7 @@ OptionValueString::SetValueFromCString (const char *value_cstr, { SetCurrentValue (value_cstr); } + NotifyValueChanged(); break; } return error; diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueUInt64.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueUInt64.cpp index 56b3a1c..3e12c03 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueUInt64.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueUInt64.cpp @@ -51,6 +51,7 @@ OptionValueUInt64::SetValueFromCString (const char *value_cstr, VarSetOperationT { case eVarSetOperationClear: Clear (); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -62,6 +63,7 @@ OptionValueUInt64::SetValueFromCString (const char *value_cstr, VarSetOperationT { m_value_was_set = true; m_current_value = value; + NotifyValueChanged(); } else { diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueUUID.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueUUID.cpp index 0141911..c228cf6 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueUUID.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueUUID.cpp @@ -45,6 +45,7 @@ OptionValueUUID::SetValueFromCString (const char *value_cstr, { case eVarSetOperationClear: Clear(); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -53,7 +54,10 @@ OptionValueUUID::SetValueFromCString (const char *value_cstr, if (m_uuid.SetFromCString(value_cstr) == 0) error.SetErrorStringWithFormat ("invalid uuid string value '%s'", value_cstr); else + { m_value_was_set = true; + NotifyValueChanged(); + } } break; diff --git a/contrib/llvm/tools/lldb/source/Interpreter/Property.cpp b/contrib/llvm/tools/lldb/source/Interpreter/Property.cpp index 4937626..7f7219f 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/Property.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/Property.cpp @@ -60,7 +60,11 @@ Property::Property (const PropertyDefinition &definition) : else m_value_sp.reset (new OptionValueBoolean(definition.default_uint_value != 0)); break; - + + case OptionValue::eTypeChar: + m_value_sp.reset(new OptionValueChar(Args::StringToChar(definition.default_cstr_value, '\0', nullptr))); + break; + case OptionValue::eTypeDictionary: // "definition.default_uint_value" is always a OptionValue::Type m_value_sp.reset (new OptionValueDictionary(OptionValue::ConvertTypeToMask((OptionValue::Type)definition.default_uint_value))); @@ -273,3 +277,12 @@ Property::DumpDescription (CommandInterpreter &interpreter, } } + +void +Property::SetValueChangedCallback (OptionValueChangedCallback callback, void *baton) +{ + if (m_value_sp) + m_value_sp->SetValueChangedCallback (callback, baton); +} + + diff --git a/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreter.cpp b/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreter.cpp index b6c46f8..45e3b44 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreter.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreter.cpp @@ -124,6 +124,7 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue, SWIGPythonUpdateSynthProviderInstance swig_update_provider, SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider, + SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider, SWIGPythonCallCommand swig_call_command, SWIGPythonCallModuleInit swig_call_module_init, SWIGPythonCreateOSPlugin swig_create_os_plugin, @@ -131,7 +132,10 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread, SWIGPythonScriptKeyword_Target swig_run_script_keyword_target, SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame, - SWIGPython_GetDynamicSetting swig_plugin_get) + SWIGPythonScriptKeyword_Value swig_run_script_keyword_value, + SWIGPython_GetDynamicSetting swig_plugin_get, + SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script, + SWIGPythonCallThreadPlan swig_call_thread_plan) { #ifndef LLDB_DISABLE_PYTHON ScriptInterpreterPython::InitializeInterpreter (python_swig_init_callback, @@ -146,6 +150,7 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call swig_get_valobj_sp_from_sbvalue, swig_update_provider, swig_mighthavechildren_provider, + swig_getvalue_provider, swig_call_command, swig_call_module_init, swig_create_os_plugin, @@ -153,6 +158,9 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call swig_run_script_keyword_thread, swig_run_script_keyword_target, swig_run_script_keyword_frame, - swig_plugin_get); + swig_run_script_keyword_value, + swig_plugin_get, + swig_thread_plan_script, + swig_call_thread_plan); #endif // #ifndef LLDB_DISABLE_PYTHON } diff --git a/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp index 1b24fea..ab15107 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -28,15 +28,20 @@ #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Breakpoint/WatchpointOptions.h" #include "lldb/Core/Communication.h" -#include "lldb/Core/ConnectionFileDescriptor.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Timer.h" +#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/Pipe.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/PythonDataObjects.h" #include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" + +#if defined(_WIN32) +#include "lldb/Host/windows/ConnectionGenericFileWindows.h" +#endif using namespace lldb; using namespace lldb_private; @@ -54,6 +59,7 @@ static ScriptInterpreter::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue static ScriptInterpreter::SWIGPythonGetValueObjectSPFromSBValue g_swig_get_valobj_sp_from_sbvalue = nullptr; static ScriptInterpreter::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = nullptr; static ScriptInterpreter::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_provider = nullptr; +static ScriptInterpreter::SWIGPythonGetValueSynthProviderInstance g_swig_getvalue_provider = nullptr; static ScriptInterpreter::SWIGPythonCallCommand g_swig_call_command = nullptr; static ScriptInterpreter::SWIGPythonCallModuleInit g_swig_call_module_init = nullptr; static ScriptInterpreter::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = nullptr; @@ -61,7 +67,10 @@ static ScriptInterpreter::SWIGPythonScriptKeyword_Process g_swig_run_script_keyw static ScriptInterpreter::SWIGPythonScriptKeyword_Thread g_swig_run_script_keyword_thread = nullptr; static ScriptInterpreter::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = nullptr; static ScriptInterpreter::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = nullptr; +static ScriptInterpreter::SWIGPythonScriptKeyword_Value g_swig_run_script_keyword_value = nullptr; static ScriptInterpreter::SWIGPython_GetDynamicSetting g_swig_plugin_get = nullptr; +static ScriptInterpreter::SWIGPythonCreateScriptedThreadPlan g_swig_thread_plan_script = nullptr; +static ScriptInterpreter::SWIGPythonCallThreadPlan g_swig_call_thread_plan = nullptr; static std::string ReadPythonBacktrace (PyObject* py_backtrace); @@ -435,19 +444,23 @@ ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags, if (in == nullptr || out == nullptr || err == nullptr) m_interpreter.GetDebugger().AdoptTopIOHandlerFilesIfInvalid (in_sp, out_sp, err_sp); - if (in == nullptr && in_sp && (on_entry_flags & Locker::NoSTDIN) == 0) - in = in_sp->GetFile().GetStream(); - if (in) - { - m_saved_stdin.Reset(sys_module_dict.GetItemForKey("stdin")); + m_saved_stdin.Reset(); - PyObject *new_file = PyFile_FromFile (in, (char *) "", (char *) "r", nullptr); - sys_module_dict.SetItemForKey ("stdin", new_file); - Py_DECREF (new_file); + if ((on_entry_flags & Locker::NoSTDIN) == 0) + { + // STDIN is enabled + if (in == nullptr && in_sp) + in = in_sp->GetFile().GetStream(); + if (in) + { + m_saved_stdin.Reset(sys_module_dict.GetItemForKey("stdin")); + // This call can deadlock your process if the file is locked + PyObject *new_file = PyFile_FromFile (in, (char *) "", (char *) "r", nullptr); + sys_module_dict.SetItemForKey ("stdin", new_file); + Py_DECREF (new_file); + } } - else - m_saved_stdin.Reset(); - + if (out == nullptr && out_sp) out = out_sp->GetFile().GetStream(); if (out) @@ -594,9 +607,16 @@ ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObjec // Set output to a temporary file so we can forward the results on to the result object Pipe pipe; - if (pipe.Open()) + Error pipe_result = pipe.CreateNew(false); + if (pipe_result.Success()) { +#if defined(_WIN32) + lldb::file_t read_file = pipe.GetReadNativeHandle(); + pipe.ReleaseReadFileDescriptor(); + std::unique_ptr<ConnectionGenericFile> conn_ap(new ConnectionGenericFile(read_file, true)); +#else std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(), true)); +#endif if (conn_ap->IsConnected()) { output_comm.SetConnection(conn_ap.release()); @@ -632,7 +652,8 @@ ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObjec Locker locker(this, ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | - (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0), + (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | + ((result && result->GetInteractive()) ? 0: Locker::NoSTDIN), ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession, in_file, @@ -708,7 +729,7 @@ public: IOHandlerPythonInterpreter (Debugger &debugger, ScriptInterpreterPython *python) : - IOHandler (debugger), + IOHandler (debugger, IOHandler::Type::PythonInterpreter), m_python(python) { @@ -1617,6 +1638,87 @@ ScriptInterpreterPython::OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP } lldb::ScriptInterpreterObjectSP +ScriptInterpreterPython::CreateScriptedThreadPlan (const char *class_name, + lldb::ThreadPlanSP thread_plan_sp) +{ + if (class_name == nullptr || class_name[0] == '\0') + return lldb::ScriptInterpreterObjectSP(); + + if (!thread_plan_sp.get()) + return lldb::ScriptInterpreterObjectSP(); + + Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger(); + ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); + ScriptInterpreterPython *python_interpreter = static_cast<ScriptInterpreterPython *>(script_interpreter); + + if (!script_interpreter) + return lldb::ScriptInterpreterObjectSP(); + + void* ret_val; + + { + Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + + ret_val = g_swig_thread_plan_script (class_name, + python_interpreter->m_dictionary_name.c_str(), + thread_plan_sp); + } + + return MakeScriptObject(ret_val); +} + +bool +ScriptInterpreterPython::ScriptedThreadPlanExplainsStop (lldb::ScriptInterpreterObjectSP implementor_sp, + Event *event, + bool &script_error) +{ + bool explains_stop = true; + if (implementor_sp) + { + Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + explains_stop = g_swig_call_thread_plan (implementor_sp->GetObject(), "explains_stop", event, script_error); + if (script_error) + return true; + } + return explains_stop; +} + +bool +ScriptInterpreterPython::ScriptedThreadPlanShouldStop (lldb::ScriptInterpreterObjectSP implementor_sp, + Event *event, + bool &script_error) +{ + bool should_stop = true; + if (implementor_sp) + { + Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + should_stop = g_swig_call_thread_plan (implementor_sp->GetObject(), "should_stop", event, script_error); + if (script_error) + return true; + } + return should_stop; +} + +lldb::StateType +ScriptInterpreterPython::ScriptedThreadPlanGetRunState (lldb::ScriptInterpreterObjectSP implementor_sp, + bool &script_error) +{ + bool should_step = false; + if (implementor_sp) + { + Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + should_step = g_swig_call_thread_plan (implementor_sp->GetObject(), "should_step", NULL, script_error); + if (script_error) + should_step = true; + } + if (should_step) + return lldb::eStateStepping; + else + return lldb::eStateRunning; +} + + +lldb::ScriptInterpreterObjectSP ScriptInterpreterPython::LoadPluginModule (const FileSpec& file_spec, lldb_private::Error& error) { @@ -1759,6 +1861,7 @@ bool ScriptInterpreterPython::GetScriptedSummary (const char *python_function_name, lldb::ValueObjectSP valobj, lldb::ScriptInterpreterObjectSP& callee_wrapper_sp, + const TypeSummaryOptions& options, std::string& retval) { @@ -1780,11 +1883,14 @@ ScriptInterpreterPython::GetScriptedSummary (const char *python_function_name, { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); { + TypeSummaryOptionsSP options_sp(new TypeSummaryOptions(options)); + Timer scoped_timer ("g_swig_typescript_callback","g_swig_typescript_callback"); ret_val = g_swig_typescript_callback (python_function_name, GetSessionDictionary().get(), valobj, &new_callee, + options_sp, retval); } } @@ -2056,6 +2162,42 @@ ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance (const lldb::Scr return ret_val; } +lldb::ValueObjectSP +ScriptInterpreterPython::GetSyntheticValue (const lldb::ScriptInterpreterObjectSP& implementor_sp) +{ + lldb::ValueObjectSP ret_val(nullptr); + + if (!implementor_sp) + return ret_val; + + void* implementor = implementor_sp->GetObject(); + + if (!implementor) + return ret_val; + + if (!g_swig_getvalue_provider || !g_swig_cast_to_sbvalue || !g_swig_get_valobj_sp_from_sbvalue) + return ret_val; + + { + Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + void* child_ptr = g_swig_getvalue_provider (implementor); + if (child_ptr != nullptr && child_ptr != Py_None) + { + lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr); + if (sb_value_ptr == nullptr) + Py_XDECREF(child_ptr); + else + ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr); + } + else + { + Py_XDECREF(child_ptr); + } + } + + return ret_val; +} + static std::string ReadPythonBacktrace (PyObject* py_backtrace) { @@ -2240,6 +2382,38 @@ ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, } return ret_val; } + +bool +ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, + ValueObject *value, + std::string& output, + Error& error) +{ + bool ret_val; + if (!value) + { + error.SetErrorString("no value"); + return false; + } + if (!impl_function || !impl_function[0]) + { + error.SetErrorString("no function to execute"); + return false; + } + if (!g_swig_run_script_keyword_value) + { + error.SetErrorString("internal helper function missing"); + return false; + } + { + ValueObjectSP value_sp(value->GetSP()); + Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + ret_val = g_swig_run_script_keyword_value (impl_function, m_dictionary_name.c_str(), value_sp, output); + if (!ret_val) + error.SetErrorString("python script evaluation failed"); + } + return ret_val; +} uint64_t replace_all(std::string& str, const std::string& oldStr, const std::string& newStr) { @@ -2426,7 +2600,8 @@ ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, const char* args, ScriptedCommandSynchronicity synchronicity, lldb_private::CommandReturnObject& cmd_retobj, - Error& error) + Error& error, + const lldb_private::ExecutionContext& exe_ctx) { if (!impl_function) { @@ -2441,6 +2616,7 @@ ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, } lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this(); + lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx)); if (!debugger_sp.get()) { @@ -2464,7 +2640,8 @@ ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, m_dictionary_name.c_str(), debugger_sp, args, - cmd_retobj); + cmd_retobj, + exe_ctx_ref_sp); } if (!ret_val) @@ -2529,6 +2706,7 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue, SWIGPythonUpdateSynthProviderInstance swig_update_provider, SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider, + SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider, SWIGPythonCallCommand swig_call_command, SWIGPythonCallModuleInit swig_call_module_init, SWIGPythonCreateOSPlugin swig_create_os_plugin, @@ -2536,7 +2714,10 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread, SWIGPythonScriptKeyword_Target swig_run_script_keyword_target, SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame, - SWIGPython_GetDynamicSetting swig_plugin_get) + SWIGPythonScriptKeyword_Value swig_run_script_keyword_value, + SWIGPython_GetDynamicSetting swig_plugin_get, + SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script, + SWIGPythonCallThreadPlan swig_call_thread_plan) { g_swig_init_callback = swig_init_callback; g_swig_breakpoint_callback = swig_breakpoint_callback; @@ -2550,6 +2731,7 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb g_swig_get_valobj_sp_from_sbvalue = swig_get_valobj_sp_from_sbvalue; g_swig_update_provider = swig_update_provider; g_swig_mighthavechildren_provider = swig_mighthavechildren_provider; + g_swig_getvalue_provider = swig_getvalue_provider; g_swig_call_command = swig_call_command; g_swig_call_module_init = swig_call_module_init; g_swig_create_os_plugin = swig_create_os_plugin; @@ -2557,7 +2739,10 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb g_swig_run_script_keyword_thread = swig_run_script_keyword_thread; g_swig_run_script_keyword_target = swig_run_script_keyword_target; g_swig_run_script_keyword_frame = swig_run_script_keyword_frame; + g_swig_run_script_keyword_value = swig_run_script_keyword_value; g_swig_plugin_get = swig_plugin_get; + g_swig_thread_plan_script = swig_thread_plan_script; + g_swig_call_thread_plan = swig_call_thread_plan; } void diff --git a/contrib/llvm/tools/lldb/source/Interpreter/embedded_interpreter.py b/contrib/llvm/tools/lldb/source/Interpreter/embedded_interpreter.py index 51a9716..10186f5 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/embedded_interpreter.py +++ b/contrib/llvm/tools/lldb/source/Interpreter/embedded_interpreter.py @@ -61,7 +61,7 @@ def get_terminal_size(fd): def readfunc_stdio(prompt): sys.stdout.write(prompt) - return sys.stdin.readline() + return sys.stdin.readline().rstrip() def run_python_interpreter (local_dict): # Pass in the dictionary, for continuity from one session to the next. |