1 //===-- ThreadPlanCallUserExpression.cpp -------------------------*- C++-*-===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Target/ThreadPlanCallUserExpression.h" 10 11 12 #include "lldb/Breakpoint/Breakpoint.h" 13 #include "lldb/Breakpoint/BreakpointLocation.h" 14 #include "lldb/Core/Address.h" 15 #include "lldb/Expression/DiagnosticManager.h" 16 #include "lldb/Expression/DynamicCheckerFunctions.h" 17 #include "lldb/Expression/UserExpression.h" 18 #include "lldb/Host/HostInfo.h" 19 #include "lldb/Target/LanguageRuntime.h" 20 #include "lldb/Target/Process.h" 21 #include "lldb/Target/RegisterContext.h" 22 #include "lldb/Target/StopInfo.h" 23 #include "lldb/Target/Target.h" 24 #include "lldb/Target/Thread.h" 25 #include "lldb/Target/ThreadPlanRunToAddress.h" 26 #include "lldb/Utility/Log.h" 27 #include "lldb/Utility/Stream.h" 28 29 using namespace lldb; 30 using namespace lldb_private; 31 32 // ThreadPlanCallUserExpression: Plan to call a single function 33 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 41 // to stop when done. 42 SetIsMasterPlan(true); 43 SetOkayToDiscard(false); 44 } 45 46 ThreadPlanCallUserExpression::~ThreadPlanCallUserExpression() {} 47 48 void ThreadPlanCallUserExpression::GetDescription( 49 Stream *s, lldb::DescriptionLevel level) { 50 if (level == eDescriptionLevelBrief) 51 s->Printf("User Expression thread plan"); 52 else 53 ThreadPlanCallFunction::GetDescription(s, level); 54 } 55 56 void ThreadPlanCallUserExpression::DidPush() { 57 ThreadPlanCallFunction::DidPush(); 58 if (m_user_expression_sp) 59 m_user_expression_sp->WillStartExecuting(); 60 } 61 62 void ThreadPlanCallUserExpression::WillPop() { 63 ThreadPlanCallFunction::WillPop(); 64 if (m_user_expression_sp) 65 m_user_expression_sp.reset(); 66 } 67 68 bool ThreadPlanCallUserExpression::MischiefManaged() { 69 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 70 71 if (IsPlanComplete()) { 72 LLDB_LOGF(log, "ThreadPlanCallFunction(%p): Completed call function plan.", 73 static_cast<void *>(this)); 74 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(); 79 80 function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize(); 81 function_stack_top = function_stack_pointer; 82 83 DiagnosticManager diagnostics; 84 85 ExecutionContext exe_ctx(GetThread()); 86 87 m_user_expression_sp->FinalizeJITExecution( 88 diagnostics, exe_ctx, m_result_var_sp, function_stack_bottom, 89 function_stack_top); 90 } 91 92 ThreadPlan::MischiefManaged(); 93 return true; 94 } else { 95 return false; 96 } 97 } 98 99 StopInfoSP ThreadPlanCallUserExpression::GetRealStopInfo() { 100 StopInfoSP stop_info_sp = ThreadPlanCallFunction::GetRealStopInfo(); 101 102 if (stop_info_sp) { 103 lldb::addr_t addr = GetStopAddress(); 104 DynamicCheckerFunctions *checkers = 105 m_thread.GetProcess()->GetDynamicCheckers(); 106 StreamString s; 107 108 if (checkers && checkers->DoCheckersExplainStop(addr, s)) 109 stop_info_sp->SetDescription(s.GetData()); 110 } 111 112 return stop_info_sp; 113 } 114 115 void ThreadPlanCallUserExpression::DoTakedown(bool success) { 116 ThreadPlanCallFunction::DoTakedown(success); 117 m_user_expression_sp->DidFinishExecuting(); 118 } 119