1 //===-- ThreadPlanCallUserExpression.cpp ----------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Target/ThreadPlanCallUserExpression.h"
11 #include "lldb/Breakpoint/Breakpoint.h"
12 #include "lldb/Breakpoint/BreakpointLocation.h"
13 #include "lldb/Core/Address.h"
14 #include "lldb/Expression/DiagnosticManager.h"
15 #include "lldb/Expression/DynamicCheckerFunctions.h"
16 #include "lldb/Expression/UserExpression.h"
17 #include "lldb/Host/HostInfo.h"
18 #include "lldb/Target/LanguageRuntime.h"
19 #include "lldb/Target/Process.h"
20 #include "lldb/Target/RegisterContext.h"
21 #include "lldb/Target/StopInfo.h"
22 #include "lldb/Target/Target.h"
23 #include "lldb/Target/Thread.h"
24 #include "lldb/Target/ThreadPlanRunToAddress.h"
25 #include "lldb/Utility/LLDBLog.h"
26 #include "lldb/Utility/Log.h"
27 #include "lldb/Utility/Stream.h"
30 using namespace lldb_private
;
32 // ThreadPlanCallUserExpression: Plan to call a single function
34 ThreadPlanCallUserExpression::ThreadPlanCallUserExpression(
35 Thread
&thread
, Address
&function
, llvm::ArrayRef
<lldb::addr_t
> args
,
36 const EvaluateExpressionOptions
&options
,
37 lldb::UserExpressionSP
&user_expression_sp
)
38 : ThreadPlanCallFunction(thread
, function
, CompilerType(), args
, options
),
39 m_user_expression_sp(user_expression_sp
) {
40 // User expressions are generally "User generated" so we should set them up
42 SetIsControllingPlan(true);
43 SetOkayToDiscard(false);
46 ThreadPlanCallUserExpression::~ThreadPlanCallUserExpression() = default;
48 void ThreadPlanCallUserExpression::GetDescription(
49 Stream
*s
, lldb::DescriptionLevel level
) {
50 if (level
== eDescriptionLevelBrief
)
51 s
->Printf("User Expression thread plan");
53 ThreadPlanCallFunction::GetDescription(s
, level
);
56 void ThreadPlanCallUserExpression::DidPush() {
57 ThreadPlanCallFunction::DidPush();
58 if (m_user_expression_sp
)
59 m_user_expression_sp
->WillStartExecuting();
62 void ThreadPlanCallUserExpression::DidPop() {
63 ThreadPlanCallFunction::DidPop();
64 if (m_user_expression_sp
)
65 m_user_expression_sp
.reset();
68 bool ThreadPlanCallUserExpression::MischiefManaged() {
69 Log
*log
= GetLog(LLDBLog::Step
);
71 if (IsPlanComplete()) {
72 LLDB_LOGF(log
, "ThreadPlanCallFunction(%p): Completed call function plan.",
73 static_cast<void *>(this));
75 if (m_manage_materialization
&& PlanSucceeded() && m_user_expression_sp
) {
76 lldb::addr_t function_stack_top
;
77 lldb::addr_t function_stack_bottom
;
78 lldb::addr_t function_stack_pointer
= GetFunctionStackPointer();
80 function_stack_bottom
= function_stack_pointer
- HostInfo::GetPageSize();
81 function_stack_top
= function_stack_pointer
;
83 DiagnosticManager diagnostics
;
85 ExecutionContext
exe_ctx(GetThread());
87 m_user_expression_sp
->FinalizeJITExecution(
88 diagnostics
, exe_ctx
, m_result_var_sp
, function_stack_bottom
,
92 ThreadPlan::MischiefManaged();
99 StopInfoSP
ThreadPlanCallUserExpression::GetRealStopInfo() {
100 StopInfoSP stop_info_sp
= ThreadPlanCallFunction::GetRealStopInfo();
103 lldb::addr_t addr
= GetStopAddress();
104 DynamicCheckerFunctions
*checkers
= m_process
.GetDynamicCheckers();
107 if (checkers
&& checkers
->DoCheckersExplainStop(addr
, s
))
108 stop_info_sp
->SetDescription(s
.GetData());
114 void ThreadPlanCallUserExpression::DoTakedown(bool success
) {
115 ThreadPlanCallFunction::DoTakedown(success
);
116 m_user_expression_sp
->DidFinishExecuting();