diff options
author | Greg Clayton <gclayton@apple.com> | 2013-11-04 19:35:17 +0000 |
---|---|---|
committer | Greg Clayton <gclayton@apple.com> | 2013-11-04 19:35:17 +0000 |
commit | 62afb9f663be1f80d80e3b25ba5fe69245bd28b9 (patch) | |
tree | e6fa5fdcf76c3390c4a8986098eb2be5d82616b9 | |
parent | cfcfee0be4fef4061834a0eabbf33b63074efec3 (diff) | |
download | bcm5719-llvm-62afb9f663be1f80d80e3b25ba5fe69245bd28b9.tar.gz bcm5719-llvm-62afb9f663be1f80d80e3b25ba5fe69245bd28b9.zip |
Added a "--debug" option to the "expression" command.
Cleaned up ClangUserExpression::Evaluate() to have only one variant that takes a "const EvaluateExpressionOptions& options" instead of taking many arguments.
The "--debug" option is designed to allow you to debug your expression by stopping at the first instruction (it enables --ignore-breakpoints=true and --unwind-on-error=false) and allowing you to step through your JIT code. It needs to be more integrated with the thread plan, so I am checking this in so Jim Ingham can make it happen.
llvm-svn: 194009
-rw-r--r-- | lldb/include/lldb/Expression/ClangUserExpression.h | 83 | ||||
-rw-r--r-- | lldb/include/lldb/Target/Target.h | 30 | ||||
-rw-r--r-- | lldb/source/Breakpoint/BreakpointLocation.cpp | 15 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectExpression.cpp | 15 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectExpression.h | 1 | ||||
-rw-r--r-- | lldb/source/Expression/ClangUserExpression.cpp | 77 | ||||
-rw-r--r-- | lldb/source/Target/Process.cpp | 53 | ||||
-rw-r--r-- | lldb/source/Target/StopInfo.cpp | 23 | ||||
-rw-r--r-- | lldb/source/Target/Target.cpp | 13 |
9 files changed, 128 insertions, 182 deletions
diff --git a/lldb/include/lldb/Expression/ClangUserExpression.h b/lldb/include/lldb/Expression/ClangUserExpression.h index 47bfebb4664..b8c3c128acf 100644 --- a/lldb/include/lldb/Expression/ClangUserExpression.h +++ b/lldb/include/lldb/Expression/ClangUserExpression.h @@ -126,13 +126,8 @@ public: /// The execution context to use when looking up entities that /// are needed for parsing (locations of variables, etc.) /// - /// @param[in] unwind_on_error - /// If true, and the execution stops before completion, we unwind the - /// function call, and return the program state to what it was before the - /// execution. If false, we leave the program in the stopped state. - /// - /// @param[in] ignore_breakpoints - /// If true, ignore breakpoints while executing the expression. + /// @param[in] options + /// Expression evaluation options. /// /// @param[in] shared_ptr_to_me /// This is a shared pointer to this ClangUserExpression. This is @@ -145,29 +140,15 @@ public: /// A pointer to direct at the persistent variable in which the /// expression's result is stored. /// - /// @param[in] try_all_threads - /// If true, then we will try to run all threads if the function doesn't complete on - /// one thread. See timeout_usec for the interaction of this variable and - /// the timeout. - /// - /// @param[in] timeout_usec - /// Timeout value (0 for no timeout). If try_all_threads is true, then we - /// will try on one thread for the lesser of .25 sec and half the total timeout. - /// then switch to running all threads, otherwise this will be the total timeout. - /// - /// /// @return /// A Process::Execution results value. //------------------------------------------------------------------ ExecutionResults Execute (Stream &error_stream, ExecutionContext &exe_ctx, - bool unwind_on_error, - bool ignore_breakpoints, + const EvaluateExpressionOptions& options, ClangUserExpressionSP &shared_ptr_to_me, - lldb::ClangExpressionVariableSP &result, - bool try_all_threads, - uint32_t timeout_usec); + lldb::ClangExpressionVariableSP &result); ThreadPlan * GetThreadPlanToExecuteJITExpression (Stream &error_stream, @@ -300,25 +281,8 @@ public: /// @param[in] exe_ctx /// The execution context to use when evaluating the expression. /// - /// @param[in] execution_policy - /// Determines whether or not to try using the IR interpreter to - /// avoid running the expression on the parser. - /// - /// @param[in] language - /// If not eLanguageTypeUnknown, a language to use when parsing - /// the expression. Currently restricted to those languages - /// supported by Clang. - /// - /// @param[in] unwind_on_error - /// True if the thread's state should be restored in the case - /// of an error. - /// - /// @param[in] ignore_breakpoints - /// If true, ignore breakpoints while executing the expression. - /// - /// @param[in] result_type - /// If not eResultTypeAny, the type of the desired result. Will - /// result in parse errors if impossible. + /// @param[in] options + /// Expression evaluation options. /// /// @param[in] expr_cstr /// A C string containing the expression to be evaluated. @@ -330,45 +294,20 @@ public: /// @param[in/out] result_valobj_sp /// If execution is successful, the result valobj is placed here. /// - /// @param[in] try_all_threads - /// If true, then we will try to run all threads if the function doesn't complete on - /// one thread. See timeout_usec for the interaction of this variable and - /// the timeout. - /// - /// @param[in] timeout_usec - /// Timeout value (0 for no timeout). If try_all_threads is true, then we - /// will try on one thread for the lesser of .25 sec and half the total timeout. - /// then switch to running all threads, otherwise this will be the total timeout. + /// @param[out] + /// Filled in with an error in case the expression evaluation + /// fails to parse, run, or evaluated. /// /// @result /// A Process::ExecutionResults value. eExecutionCompleted for success. //------------------------------------------------------------------ static ExecutionResults Evaluate (ExecutionContext &exe_ctx, - lldb_private::ExecutionPolicy execution_policy, - lldb::LanguageType language, - ResultType desired_type, - bool unwind_on_error, - bool ignore_breakpoints, + const EvaluateExpressionOptions& options, const char *expr_cstr, const char *expr_prefix, lldb::ValueObjectSP &result_valobj_sp, - bool try_all_threads, - uint32_t timeout_usec); - - static ExecutionResults - EvaluateWithError (ExecutionContext &exe_ctx, - lldb_private::ExecutionPolicy execution_policy, - lldb::LanguageType language, - ResultType desired_type, - bool unwind_on_error, - bool ignore_breakpoints, - const char *expr_cstr, - const char *expr_prefix, - lldb::ValueObjectSP &result_valobj_sp, - Error &error, - bool try_all_threads, - uint32_t timeout_usec); + Error &error); static const Error::ValueType kNoResult = 0x1001; ///< ValueObject::GetError() returns this if there is no result from the expression. private: diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index a7609d37116..c20225c093d 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -184,11 +184,13 @@ public: static const uint32_t default_timeout = 500000; EvaluateExpressionOptions() : m_execution_policy(eExecutionPolicyOnlyWhenNeeded), + m_language (lldb::eLanguageTypeUnknown), m_coerce_to_id(false), m_unwind_on_error(true), m_ignore_breakpoints (false), m_keep_in_memory(false), m_run_others(true), + m_debug(false), m_use_dynamic(lldb::eNoDynamicValues), m_timeout_usec(default_timeout) {} @@ -206,6 +208,19 @@ public: return *this; } + lldb::LanguageType + GetLanguage() const + { + return m_language; + } + + EvaluateExpressionOptions& + SetLanguage(lldb::LanguageType language) + { + m_language = language; + return *this; + } + bool DoesCoerceToId () const { @@ -297,13 +312,28 @@ public: return *this; } + bool + GetDebug() const + { + return m_debug; + } + + EvaluateExpressionOptions& + SetDebug(bool b) + { + m_debug = b; + return *this; + } + private: ExecutionPolicy m_execution_policy; + lldb::LanguageType m_language; bool m_coerce_to_id; bool m_unwind_on_error; bool m_ignore_breakpoints; bool m_keep_in_memory; bool m_run_others; + bool m_debug; lldb::DynamicValueType m_use_dynamic; uint32_t m_timeout_usec; }; diff --git a/lldb/source/Breakpoint/BreakpointLocation.cpp b/lldb/source/Breakpoint/BreakpointLocation.cpp index bd165facd28..17568c28b50 100644 --- a/lldb/source/Breakpoint/BreakpointLocation.cpp +++ b/lldb/source/Breakpoint/BreakpointLocation.cpp @@ -291,9 +291,11 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error) // constructor errors up to the debugger's Async I/O. ValueObjectSP result_value_sp; - const bool unwind_on_error = true; - const bool ignore_breakpoints = true; - const bool try_all_threads = true; + + EvaluateExpressionOptions options; + options.SetUnwindOnError(true); + options.SetIgnoreBreakpoints(true); + options.SetRunOthers(true); Error expr_error; @@ -304,12 +306,9 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error) ExecutionResults result_code = m_user_expression_sp->Execute(execution_errors, exe_ctx, - unwind_on_error, - ignore_breakpoints, + options, m_user_expression_sp, - result_variable_sp, - try_all_threads, - ClangUserExpression::kDefaultTimeout); + result_variable_sp); bool ret; diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 8b04da600f4..6d44f71b8d9 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -64,6 +64,7 @@ CommandObjectExpression::CommandOptions::g_option_table[] = { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"}, { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."}, { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."}, + { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", 'g', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "When specified, debug the JIT code by setting a breakpoint on the first instruction and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0)."}, { LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, g_description_verbosity_type, 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."}, }; @@ -147,7 +148,13 @@ CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &int if (!error.Success()) error.SetErrorStringWithFormat ("unrecognized value for description-verbosity '%s'", option_arg); break; - + + case 'g': + debug = true; + unwind_on_error = false; + ignore_breakpoints = false; + break; + default: error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); break; @@ -174,6 +181,7 @@ CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpret show_summary = true; try_all_threads = true; timeout = 0; + debug = false; m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact; } @@ -361,7 +369,10 @@ CommandObjectExpression::EvaluateExpression .SetKeepInMemory(keep_in_memory) .SetUseDynamic(m_varobj_options.use_dynamic) .SetRunOthers(m_command_options.try_all_threads) - .SetTimeoutUsec(m_command_options.timeout); + .SetDebug(m_command_options.debug); + + if (m_command_options.timeout > 0) + options.SetTimeoutUsec(m_command_options.timeout); exe_results = target->EvaluateExpression (expr, exe_ctx.GetFramePtr(), diff --git a/lldb/source/Commands/CommandObjectExpression.h b/lldb/source/Commands/CommandObjectExpression.h index a62a21287c2..e0703a22a4c 100644 --- a/lldb/source/Commands/CommandObjectExpression.h +++ b/lldb/source/Commands/CommandObjectExpression.h @@ -55,6 +55,7 @@ public: bool ignore_breakpoints; bool show_types; bool show_summary; + bool debug; uint32_t timeout; bool try_all_threads; LanguageRuntimeDescriptionDisplayVerbosity m_verbosity; diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp index c9196533974..e4f2830ba25 100644 --- a/lldb/source/Expression/ClangUserExpression.cpp +++ b/lldb/source/Expression/ClangUserExpression.cpp @@ -784,12 +784,9 @@ ClangUserExpression::FinalizeJITExecution (Stream &error_stream, ExecutionResults ClangUserExpression::Execute (Stream &error_stream, ExecutionContext &exe_ctx, - bool unwind_on_error, - bool ignore_breakpoints, + const EvaluateExpressionOptions& options, ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me, - lldb::ClangExpressionVariableSP &result, - bool run_others, - uint32_t timeout_usec) + lldb::ClangExpressionVariableSP &result) { // The expression log is quite verbose, and if you're just tracking the execution of the // expression, it's quite convenient to have these logs come out with the STEP log as well. @@ -855,9 +852,18 @@ ClangUserExpression::Execute (Stream &error_stream, } else { + const uint32_t timeout_usec = options.GetTimeoutUsec(); + const bool debug = options.GetDebug(); + const bool unwind_on_error = debug ? false : options.DoesUnwindOnError(); + const bool ignore_breakpoints = debug ? false : options.DoesIgnoreBreakpoints(); const bool stop_others = true; - const bool try_all_threads = run_others; - + const bool try_all_threads = options.GetRunOthers(); + lldb::BreakpointSP debug_bkpt_sp; + if (debug) + { + // TODO: push this down into the thread plan and let the plan manage it + debug_bkpt_sp = exe_ctx.GetTargetRef().CreateBreakpoint(m_jit_start_addr, false, false); + } Address wrapper_address (m_jit_start_addr); lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(), wrapper_address, @@ -892,6 +898,11 @@ ClangUserExpression::Execute (Stream &error_stream, timeout_usec, error_stream); + if (debug_bkpt_sp) + { + exe_ctx.GetTargetRef().RemoveBreakpointByID(debug_bkpt_sp->GetID()); + } + if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); @@ -946,48 +957,17 @@ ClangUserExpression::Execute (Stream &error_stream, ExecutionResults ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, - lldb_private::ExecutionPolicy execution_policy, - lldb::LanguageType language, - ResultType desired_type, - bool unwind_on_error, - bool ignore_breakpoints, + const EvaluateExpressionOptions& options, const char *expr_cstr, const char *expr_prefix, lldb::ValueObjectSP &result_valobj_sp, - bool run_others, - uint32_t timeout_usec) -{ - Error error; - return EvaluateWithError (exe_ctx, - execution_policy, - language, - desired_type, - unwind_on_error, - ignore_breakpoints, - expr_cstr, - expr_prefix, - result_valobj_sp, - error, - run_others, - timeout_usec); -} - -ExecutionResults -ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx, - lldb_private::ExecutionPolicy execution_policy, - lldb::LanguageType language, - ResultType desired_type, - bool unwind_on_error, - bool ignore_breakpoints, - const char *expr_cstr, - const char *expr_prefix, - lldb::ValueObjectSP &result_valobj_sp, - Error &error, - bool run_others, - uint32_t timeout_usec) + Error &error) { Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); + lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); + const lldb::LanguageType language = options.GetLanguage(); + const ResultType desired_type = options.DoesCoerceToId() ? ClangUserExpression::eResultTypeId : ClangUserExpression::eResultTypeAny; ExecutionResults execution_results = eExecutionSetupError; Process *process = exe_ctx.GetProcessPtr(); @@ -1045,13 +1025,10 @@ ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx, log->Printf("== [ClangUserExpression::Evaluate] Executing expression =="); execution_results = user_expression_sp->Execute (error_stream, - exe_ctx, - unwind_on_error, - ignore_breakpoints, - user_expression_sp, - expr_result, - run_others, - timeout_usec); + exe_ctx, + options, + user_expression_sp, + expr_result); if (execution_results != eExecutionCompleted) { diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 738ed5f9fee..fcab7aff4a9 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -1814,35 +1814,36 @@ Process::LoadImage (const FileSpec &image_spec, Error &error) { ExecutionContext exe_ctx; frame_sp->CalculateExecutionContext (exe_ctx); - const bool unwind_on_error = true; - const bool ignore_breakpoints = true; + EvaluateExpressionOptions expr_options; + expr_options.SetUnwindOnError(true); + expr_options.SetIgnoreBreakpoints(true); + expr_options.SetExecutionPolicy(eExecutionPolicyAlways); StreamString expr; expr.Printf("dlopen (\"%s\", 2)", path); const char *prefix = "extern \"C\" void* dlopen (const char *path, int mode);\n"; lldb::ValueObjectSP result_valobj_sp; + Error expr_error; ClangUserExpression::Evaluate (exe_ctx, - eExecutionPolicyAlways, - lldb::eLanguageTypeUnknown, - ClangUserExpression::eResultTypeAny, - unwind_on_error, - ignore_breakpoints, + expr_options, expr.GetData(), prefix, result_valobj_sp, - true, - ClangUserExpression::kDefaultTimeout); - error = result_valobj_sp->GetError(); - if (error.Success()) + expr_error); + if (expr_error.Success()) { - Scalar scalar; - if (result_valobj_sp->ResolveValue (scalar)) + error = result_valobj_sp->GetError(); + if (error.Success()) { - addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS); - if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS) + Scalar scalar; + if (result_valobj_sp->ResolveValue (scalar)) { - uint32_t image_token = m_image_tokens.size(); - m_image_tokens.push_back (image_ptr); - return image_token; + addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS); + if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS) + { + uint32_t image_token = m_image_tokens.size(); + m_image_tokens.push_back (image_ptr); + return image_token; + } } } } @@ -1891,23 +1892,21 @@ Process::UnloadImage (uint32_t image_token) { ExecutionContext exe_ctx; frame_sp->CalculateExecutionContext (exe_ctx); - const bool unwind_on_error = true; - const bool ignore_breakpoints = true; + EvaluateExpressionOptions expr_options; + expr_options.SetUnwindOnError(true); + expr_options.SetIgnoreBreakpoints(true); + expr_options.SetExecutionPolicy(eExecutionPolicyAlways); StreamString expr; expr.Printf("dlclose ((void *)0x%" PRIx64 ")", image_addr); const char *prefix = "extern \"C\" int dlclose(void* handle);\n"; lldb::ValueObjectSP result_valobj_sp; + Error expr_error; ClangUserExpression::Evaluate (exe_ctx, - eExecutionPolicyAlways, - lldb::eLanguageTypeUnknown, - ClangUserExpression::eResultTypeAny, - unwind_on_error, - ignore_breakpoints, + expr_options, expr.GetData(), prefix, result_valobj_sp, - true, - ClangUserExpression::kDefaultTimeout); + expr_error); if (result_valobj_sp->GetError().Success()) { Scalar scalar; diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp index 81b9d866f71..914969a633e 100644 --- a/lldb/source/Target/StopInfo.cpp +++ b/lldb/source/Target/StopInfo.cpp @@ -694,22 +694,17 @@ protected: // We need to make sure the user sees any parse errors in their condition, so we'll hook the // constructor errors up to the debugger's Async I/O. ExecutionResults result_code; + EvaluateExpressionOptions expr_options; + expr_options.SetUnwindOnError(true); + expr_options.SetIgnoreBreakpoints(true); ValueObjectSP result_value_sp; - const bool unwind_on_error = true; - const bool ignore_breakpoints = true; Error error; - result_code = ClangUserExpression::EvaluateWithError (exe_ctx, - eExecutionPolicyOnlyWhenNeeded, - lldb::eLanguageTypeUnknown, - ClangUserExpression::eResultTypeAny, - unwind_on_error, - ignore_breakpoints, - wp_sp->GetConditionText(), - NULL, - result_value_sp, - error, - true, - ClangUserExpression::kDefaultTimeout); + result_code = ClangUserExpression::Evaluate (exe_ctx, + expr_options, + wp_sp->GetConditionText(), + NULL, + result_value_sp, + error); if (result_code == eExecutionCompleted) { if (result_value_sp) diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index c92a2cc3a4a..f93ae502fd7 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -1879,18 +1879,13 @@ Target::EvaluateExpression else { const char *prefix = GetExpressionPrefixContentsAsCString(); - + Error error; execution_results = ClangUserExpression::Evaluate (exe_ctx, - options.GetExecutionPolicy(), - lldb::eLanguageTypeUnknown, - options.DoesCoerceToId() ? ClangUserExpression::eResultTypeId : ClangUserExpression::eResultTypeAny, - options.DoesUnwindOnError(), - options.DoesIgnoreBreakpoints(), - expr_cstr, + options, + expr_cstr, prefix, result_valobj_sp, - options.GetRunOthers(), - options.GetTimeoutUsec()); + error); } m_suppress_stop_hooks = old_suppress_value; |