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