118 lines · cpp
1//===-- ThreadPlanCallUserExpression.cpp ----------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Target/ThreadPlanCallUserExpression.h"10 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"28 29using namespace lldb;30using namespace lldb_private;31 32// ThreadPlanCallUserExpression: Plan to call a single function33 34ThreadPlanCallUserExpression::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 up41 // to stop when done.42 SetIsControllingPlan(true);43 SetOkayToDiscard(false);44}45 46ThreadPlanCallUserExpression::~ThreadPlanCallUserExpression() = default;47 48void ThreadPlanCallUserExpression::GetDescription(49 Stream *s, lldb::DescriptionLevel level) {50 if (level == eDescriptionLevelBrief)51 s->Printf("User Expression thread plan");52 else53 ThreadPlanCallFunction::GetDescription(s, level);54}55 56void ThreadPlanCallUserExpression::DidPush() {57 ThreadPlanCallFunction::DidPush();58 if (m_user_expression_sp)59 m_user_expression_sp->WillStartExecuting();60}61 62void ThreadPlanCallUserExpression::DidPop() {63 ThreadPlanCallFunction::DidPop();64 if (m_user_expression_sp)65 m_user_expression_sp.reset();66}67 68bool ThreadPlanCallUserExpression::MischiefManaged() {69 Log *log = GetLog(LLDBLog::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 99StopInfoSP ThreadPlanCallUserExpression::GetRealStopInfo() {100 StopInfoSP stop_info_sp = ThreadPlanCallFunction::GetRealStopInfo();101 102 if (stop_info_sp) {103 lldb::addr_t addr = GetStopAddress();104 DynamicCheckerFunctions *checkers = m_process.GetDynamicCheckers();105 StreamString s;106 107 if (checkers && checkers->DoCheckersExplainStop(addr, s))108 stop_info_sp->SetDescription(s.GetData());109 }110 111 return stop_info_sp;112}113 114void ThreadPlanCallUserExpression::DoTakedown(bool success) {115 ThreadPlanCallFunction::DoTakedown(success);116 m_user_expression_sp->DidFinishExecuting();117}118