| //===-- ThreadPlanCallUserExpression.cpp ----------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "lldb/Target/ThreadPlanCallUserExpression.h" | |
| #include "lldb/Breakpoint/Breakpoint.h" | |
| #include "lldb/Breakpoint/BreakpointLocation.h" | |
| #include "lldb/Core/Address.h" | |
| #include "lldb/Expression/DiagnosticManager.h" | |
| #include "lldb/Expression/DynamicCheckerFunctions.h" | |
| #include "lldb/Expression/UserExpression.h" | |
| #include "lldb/Host/HostInfo.h" | |
| #include "lldb/Target/LanguageRuntime.h" | |
| #include "lldb/Target/Process.h" | |
| #include "lldb/Target/RegisterContext.h" | |
| #include "lldb/Target/StopInfo.h" | |
| #include "lldb/Target/Target.h" | |
| #include "lldb/Target/Thread.h" | |
| #include "lldb/Target/ThreadPlanRunToAddress.h" | |
| #include "lldb/Utility/LLDBLog.h" | |
| #include "lldb/Utility/Log.h" | |
| #include "lldb/Utility/Stream.h" | |
| using namespace lldb; | |
| using namespace lldb_private; | |
| // ThreadPlanCallUserExpression: Plan to call a single function | |
| ThreadPlanCallUserExpression::ThreadPlanCallUserExpression( | |
| Thread &thread, Address &function, llvm::ArrayRef<lldb::addr_t> args, | |
| const EvaluateExpressionOptions &options, | |
| lldb::UserExpressionSP &user_expression_sp) | |
| : ThreadPlanCallFunction(thread, function, CompilerType(), args, options), | |
| m_user_expression_sp(user_expression_sp) { | |
| // User expressions are generally "User generated" so we should set them up | |
| // to stop when done. | |
| SetIsControllingPlan(true); | |
| SetOkayToDiscard(false); | |
| } | |
| ThreadPlanCallUserExpression::~ThreadPlanCallUserExpression() = default; | |
| void ThreadPlanCallUserExpression::GetDescription( | |
| Stream *s, lldb::DescriptionLevel level) { | |
| if (level == eDescriptionLevelBrief) | |
| s->PutCString("User Expression thread plan"); | |
| else | |
| ThreadPlanCallFunction::GetDescription(s, level); | |
| } | |
| void ThreadPlanCallUserExpression::DidPush() { | |
| ThreadPlanCallFunction::DidPush(); | |
| if (m_user_expression_sp) | |
| m_user_expression_sp->WillStartExecuting(); | |
| } | |
| void ThreadPlanCallUserExpression::DidPop() { | |
| ThreadPlanCallFunction::DidPop(); | |
| if (m_user_expression_sp) | |
| m_user_expression_sp.reset(); | |
| } | |
| bool ThreadPlanCallUserExpression::MischiefManaged() { | |
| Log *log = GetLog(LLDBLog::Step); | |
| if (IsPlanComplete()) { | |
| LLDB_LOGF(log, "ThreadPlanCallFunction(%p): Completed call function plan.", | |
| static_cast<void *>(this)); | |
| if (m_manage_materialization && PlanSucceeded() && m_user_expression_sp) { | |
| lldb::addr_t function_stack_top; | |
| lldb::addr_t function_stack_bottom; | |
| lldb::addr_t function_stack_pointer = GetFunctionStackPointer(); | |
| function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize(); | |
| function_stack_top = function_stack_pointer; | |
| DiagnosticManager diagnostics; | |
| ExecutionContext exe_ctx(GetThread()); | |
| m_user_expression_sp->FinalizeJITExecution( | |
| diagnostics, exe_ctx, m_result_var_sp, function_stack_bottom, | |
| function_stack_top); | |
| } | |
| ThreadPlan::MischiefManaged(); | |
| return true; | |
| } else { | |
| return false; | |
| } | |
| } | |
| StopInfoSP ThreadPlanCallUserExpression::GetRealStopInfo() { | |
| StopInfoSP stop_info_sp = ThreadPlanCallFunction::GetRealStopInfo(); | |
| if (stop_info_sp) { | |
| lldb::addr_t addr = GetStopAddress(); | |
| DynamicCheckerFunctions *checkers = m_process.GetDynamicCheckers(); | |
| StreamString s; | |
| if (checkers && checkers->DoCheckersExplainStop(addr, s)) | |
| stop_info_sp->SetDescription(s.GetData()); | |
| } | |
| return stop_info_sp; | |
| } | |
| void ThreadPlanCallUserExpression::DoTakedown(bool success) { | |
| ThreadPlanCallFunction::DoTakedown(success); | |
| m_user_expression_sp->DidFinishExecuting(); | |
| } |