15ffd83dbSDimitry Andric //===-- ThreadPlanCallUserExpression.cpp ----------------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanCallUserExpression.h" 10*0b57cec5SDimitry Andric 11*0b57cec5SDimitry Andric 12*0b57cec5SDimitry Andric #include "lldb/Breakpoint/Breakpoint.h" 13*0b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointLocation.h" 14*0b57cec5SDimitry Andric #include "lldb/Core/Address.h" 15*0b57cec5SDimitry Andric #include "lldb/Expression/DiagnosticManager.h" 16*0b57cec5SDimitry Andric #include "lldb/Expression/DynamicCheckerFunctions.h" 17*0b57cec5SDimitry Andric #include "lldb/Expression/UserExpression.h" 18*0b57cec5SDimitry Andric #include "lldb/Host/HostInfo.h" 19*0b57cec5SDimitry Andric #include "lldb/Target/LanguageRuntime.h" 20*0b57cec5SDimitry Andric #include "lldb/Target/Process.h" 21*0b57cec5SDimitry Andric #include "lldb/Target/RegisterContext.h" 22*0b57cec5SDimitry Andric #include "lldb/Target/StopInfo.h" 23*0b57cec5SDimitry Andric #include "lldb/Target/Target.h" 24*0b57cec5SDimitry Andric #include "lldb/Target/Thread.h" 25*0b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanRunToAddress.h" 26*0b57cec5SDimitry Andric #include "lldb/Utility/Log.h" 27*0b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric using namespace lldb; 30*0b57cec5SDimitry Andric using namespace lldb_private; 31*0b57cec5SDimitry Andric 32*0b57cec5SDimitry Andric // ThreadPlanCallUserExpression: Plan to call a single function 33*0b57cec5SDimitry Andric 34*0b57cec5SDimitry Andric ThreadPlanCallUserExpression::ThreadPlanCallUserExpression( 35*0b57cec5SDimitry Andric Thread &thread, Address &function, llvm::ArrayRef<lldb::addr_t> args, 36*0b57cec5SDimitry Andric const EvaluateExpressionOptions &options, 37*0b57cec5SDimitry Andric lldb::UserExpressionSP &user_expression_sp) 38*0b57cec5SDimitry Andric : ThreadPlanCallFunction(thread, function, CompilerType(), args, options), 39*0b57cec5SDimitry Andric m_user_expression_sp(user_expression_sp) { 40*0b57cec5SDimitry Andric // User expressions are generally "User generated" so we should set them up 41*0b57cec5SDimitry Andric // to stop when done. 42*0b57cec5SDimitry Andric SetIsMasterPlan(true); 43*0b57cec5SDimitry Andric SetOkayToDiscard(false); 44*0b57cec5SDimitry Andric } 45*0b57cec5SDimitry Andric 46*0b57cec5SDimitry Andric ThreadPlanCallUserExpression::~ThreadPlanCallUserExpression() {} 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric void ThreadPlanCallUserExpression::GetDescription( 49*0b57cec5SDimitry Andric Stream *s, lldb::DescriptionLevel level) { 50*0b57cec5SDimitry Andric if (level == eDescriptionLevelBrief) 51*0b57cec5SDimitry Andric s->Printf("User Expression thread plan"); 52*0b57cec5SDimitry Andric else 53*0b57cec5SDimitry Andric ThreadPlanCallFunction::GetDescription(s, level); 54*0b57cec5SDimitry Andric } 55*0b57cec5SDimitry Andric 56*0b57cec5SDimitry Andric void ThreadPlanCallUserExpression::DidPush() { 57*0b57cec5SDimitry Andric ThreadPlanCallFunction::DidPush(); 58*0b57cec5SDimitry Andric if (m_user_expression_sp) 59*0b57cec5SDimitry Andric m_user_expression_sp->WillStartExecuting(); 60*0b57cec5SDimitry Andric } 61*0b57cec5SDimitry Andric 62*0b57cec5SDimitry Andric void ThreadPlanCallUserExpression::WillPop() { 63*0b57cec5SDimitry Andric ThreadPlanCallFunction::WillPop(); 64*0b57cec5SDimitry Andric if (m_user_expression_sp) 65*0b57cec5SDimitry Andric m_user_expression_sp.reset(); 66*0b57cec5SDimitry Andric } 67*0b57cec5SDimitry Andric 68*0b57cec5SDimitry Andric bool ThreadPlanCallUserExpression::MischiefManaged() { 69*0b57cec5SDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 70*0b57cec5SDimitry Andric 71*0b57cec5SDimitry Andric if (IsPlanComplete()) { 729dba64beSDimitry Andric LLDB_LOGF(log, "ThreadPlanCallFunction(%p): Completed call function plan.", 73*0b57cec5SDimitry Andric static_cast<void *>(this)); 74*0b57cec5SDimitry Andric 75*0b57cec5SDimitry Andric if (m_manage_materialization && PlanSucceeded() && m_user_expression_sp) { 76*0b57cec5SDimitry Andric lldb::addr_t function_stack_top; 77*0b57cec5SDimitry Andric lldb::addr_t function_stack_bottom; 78*0b57cec5SDimitry Andric lldb::addr_t function_stack_pointer = GetFunctionStackPointer(); 79*0b57cec5SDimitry Andric 80*0b57cec5SDimitry Andric function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize(); 81*0b57cec5SDimitry Andric function_stack_top = function_stack_pointer; 82*0b57cec5SDimitry Andric 83*0b57cec5SDimitry Andric DiagnosticManager diagnostics; 84*0b57cec5SDimitry Andric 85*0b57cec5SDimitry Andric ExecutionContext exe_ctx(GetThread()); 86*0b57cec5SDimitry Andric 87*0b57cec5SDimitry Andric m_user_expression_sp->FinalizeJITExecution( 88*0b57cec5SDimitry Andric diagnostics, exe_ctx, m_result_var_sp, function_stack_bottom, 89*0b57cec5SDimitry Andric function_stack_top); 90*0b57cec5SDimitry Andric } 91*0b57cec5SDimitry Andric 92*0b57cec5SDimitry Andric ThreadPlan::MischiefManaged(); 93*0b57cec5SDimitry Andric return true; 94*0b57cec5SDimitry Andric } else { 95*0b57cec5SDimitry Andric return false; 96*0b57cec5SDimitry Andric } 97*0b57cec5SDimitry Andric } 98*0b57cec5SDimitry Andric 99*0b57cec5SDimitry Andric StopInfoSP ThreadPlanCallUserExpression::GetRealStopInfo() { 100*0b57cec5SDimitry Andric StopInfoSP stop_info_sp = ThreadPlanCallFunction::GetRealStopInfo(); 101*0b57cec5SDimitry Andric 102*0b57cec5SDimitry Andric if (stop_info_sp) { 103*0b57cec5SDimitry Andric lldb::addr_t addr = GetStopAddress(); 1045ffd83dbSDimitry Andric DynamicCheckerFunctions *checkers = m_process.GetDynamicCheckers(); 105*0b57cec5SDimitry Andric StreamString s; 106*0b57cec5SDimitry Andric 107*0b57cec5SDimitry Andric if (checkers && checkers->DoCheckersExplainStop(addr, s)) 108*0b57cec5SDimitry Andric stop_info_sp->SetDescription(s.GetData()); 109*0b57cec5SDimitry Andric } 110*0b57cec5SDimitry Andric 111*0b57cec5SDimitry Andric return stop_info_sp; 112*0b57cec5SDimitry Andric } 113*0b57cec5SDimitry Andric 114*0b57cec5SDimitry Andric void ThreadPlanCallUserExpression::DoTakedown(bool success) { 115*0b57cec5SDimitry Andric ThreadPlanCallFunction::DoTakedown(success); 116*0b57cec5SDimitry Andric m_user_expression_sp->DidFinishExecuting(); 117*0b57cec5SDimitry Andric } 118