xref: /src/contrib/llvm-project/lldb/source/Target/ThreadPlanCallUserExpression.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1cfca06d7SDimitry Andric //===-- ThreadPlanCallUserExpression.cpp ----------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f034231aSEd Maste #include "lldb/Target/ThreadPlanCallUserExpression.h"
10f034231aSEd Maste 
11f034231aSEd Maste #include "lldb/Breakpoint/Breakpoint.h"
12f034231aSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h"
13f034231aSEd Maste #include "lldb/Core/Address.h"
14f3fbd1c0SDimitry Andric #include "lldb/Expression/DiagnosticManager.h"
155f29bb8aSDimitry Andric #include "lldb/Expression/DynamicCheckerFunctions.h"
16f3fbd1c0SDimitry Andric #include "lldb/Expression/UserExpression.h"
170cac4ca3SEd Maste #include "lldb/Host/HostInfo.h"
18f034231aSEd Maste #include "lldb/Target/LanguageRuntime.h"
19f034231aSEd Maste #include "lldb/Target/Process.h"
20f034231aSEd Maste #include "lldb/Target/RegisterContext.h"
21f034231aSEd Maste #include "lldb/Target/StopInfo.h"
22f034231aSEd Maste #include "lldb/Target/Target.h"
23f034231aSEd Maste #include "lldb/Target/Thread.h"
24f034231aSEd Maste #include "lldb/Target/ThreadPlanRunToAddress.h"
25145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
2674a628f7SDimitry Andric #include "lldb/Utility/Log.h"
2774a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
28f034231aSEd Maste 
29f034231aSEd Maste using namespace lldb;
30f034231aSEd Maste using namespace lldb_private;
31f034231aSEd Maste 
32f034231aSEd Maste // ThreadPlanCallUserExpression: Plan to call a single function
33f034231aSEd Maste 
ThreadPlanCallUserExpression(Thread & thread,Address & function,llvm::ArrayRef<lldb::addr_t> args,const EvaluateExpressionOptions & options,lldb::UserExpressionSP & user_expression_sp)3414f1b3e8SDimitry Andric ThreadPlanCallUserExpression::ThreadPlanCallUserExpression(
3514f1b3e8SDimitry Andric     Thread &thread, Address &function, llvm::ArrayRef<lldb::addr_t> args,
3686758c71SEd Maste     const EvaluateExpressionOptions &options,
3714f1b3e8SDimitry Andric     lldb::UserExpressionSP &user_expression_sp)
3814f1b3e8SDimitry Andric     : ThreadPlanCallFunction(thread, function, CompilerType(), args, options),
3914f1b3e8SDimitry Andric       m_user_expression_sp(user_expression_sp) {
40f73363f1SDimitry Andric   // User expressions are generally "User generated" so we should set them up
41f73363f1SDimitry Andric   // to stop when done.
42c0981da4SDimitry Andric   SetIsControllingPlan(true);
43f034231aSEd Maste   SetOkayToDiscard(false);
44f034231aSEd Maste }
45f034231aSEd Maste 
46344a3780SDimitry Andric ThreadPlanCallUserExpression::~ThreadPlanCallUserExpression() = default;
47f034231aSEd Maste 
GetDescription(Stream * s,lldb::DescriptionLevel level)4814f1b3e8SDimitry Andric void ThreadPlanCallUserExpression::GetDescription(
4914f1b3e8SDimitry Andric     Stream *s, lldb::DescriptionLevel level) {
500cac4ca3SEd Maste   if (level == eDescriptionLevelBrief)
510cac4ca3SEd Maste     s->Printf("User Expression thread plan");
520cac4ca3SEd Maste   else
53f034231aSEd Maste     ThreadPlanCallFunction::GetDescription(s, level);
54f034231aSEd Maste }
55f034231aSEd Maste 
DidPush()568b4000f1SDimitry Andric void ThreadPlanCallUserExpression::DidPush() {
578b4000f1SDimitry Andric   ThreadPlanCallFunction::DidPush();
588b4000f1SDimitry Andric   if (m_user_expression_sp)
598b4000f1SDimitry Andric     m_user_expression_sp->WillStartExecuting();
608b4000f1SDimitry Andric }
618b4000f1SDimitry Andric 
DidPop()62c0981da4SDimitry Andric void ThreadPlanCallUserExpression::DidPop() {
63c0981da4SDimitry Andric   ThreadPlanCallFunction::DidPop();
640cac4ca3SEd Maste   if (m_user_expression_sp)
650cac4ca3SEd Maste     m_user_expression_sp.reset();
660cac4ca3SEd Maste }
670cac4ca3SEd Maste 
MischiefManaged()6814f1b3e8SDimitry Andric bool ThreadPlanCallUserExpression::MischiefManaged() {
69145449b1SDimitry Andric   Log *log = GetLog(LLDBLog::Step);
700cac4ca3SEd Maste 
7114f1b3e8SDimitry Andric   if (IsPlanComplete()) {
72ead24645SDimitry Andric     LLDB_LOGF(log, "ThreadPlanCallFunction(%p): Completed call function plan.",
730cac4ca3SEd Maste               static_cast<void *>(this));
740cac4ca3SEd Maste 
7514f1b3e8SDimitry Andric     if (m_manage_materialization && PlanSucceeded() && m_user_expression_sp) {
760cac4ca3SEd Maste       lldb::addr_t function_stack_top;
770cac4ca3SEd Maste       lldb::addr_t function_stack_bottom;
780cac4ca3SEd Maste       lldb::addr_t function_stack_pointer = GetFunctionStackPointer();
790cac4ca3SEd Maste 
800cac4ca3SEd Maste       function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
810cac4ca3SEd Maste       function_stack_top = function_stack_pointer;
820cac4ca3SEd Maste 
83f3fbd1c0SDimitry Andric       DiagnosticManager diagnostics;
840cac4ca3SEd Maste 
850cac4ca3SEd Maste       ExecutionContext exe_ctx(GetThread());
860cac4ca3SEd Maste 
8714f1b3e8SDimitry Andric       m_user_expression_sp->FinalizeJITExecution(
8814f1b3e8SDimitry Andric           diagnostics, exe_ctx, m_result_var_sp, function_stack_bottom,
89f3fbd1c0SDimitry Andric           function_stack_top);
900cac4ca3SEd Maste     }
910cac4ca3SEd Maste 
920cac4ca3SEd Maste     ThreadPlan::MischiefManaged();
930cac4ca3SEd Maste     return true;
9414f1b3e8SDimitry Andric   } else {
950cac4ca3SEd Maste     return false;
960cac4ca3SEd Maste   }
970cac4ca3SEd Maste }
980cac4ca3SEd Maste 
GetRealStopInfo()9914f1b3e8SDimitry Andric StopInfoSP ThreadPlanCallUserExpression::GetRealStopInfo() {
100f034231aSEd Maste   StopInfoSP stop_info_sp = ThreadPlanCallFunction::GetRealStopInfo();
101f034231aSEd Maste 
10214f1b3e8SDimitry Andric   if (stop_info_sp) {
103f034231aSEd Maste     lldb::addr_t addr = GetStopAddress();
104cfca06d7SDimitry Andric     DynamicCheckerFunctions *checkers = m_process.GetDynamicCheckers();
105f034231aSEd Maste     StreamString s;
106f034231aSEd Maste 
107f034231aSEd Maste     if (checkers && checkers->DoCheckersExplainStop(addr, s))
108f034231aSEd Maste       stop_info_sp->SetDescription(s.GetData());
109f034231aSEd Maste   }
110f034231aSEd Maste 
111f034231aSEd Maste   return stop_info_sp;
112f034231aSEd Maste }
1138b4000f1SDimitry Andric 
DoTakedown(bool success)1148b4000f1SDimitry Andric void ThreadPlanCallUserExpression::DoTakedown(bool success) {
1158b4000f1SDimitry Andric   ThreadPlanCallFunction::DoTakedown(success);
1168b4000f1SDimitry Andric   m_user_expression_sp->DidFinishExecuting();
1178b4000f1SDimitry Andric }
118