1 //===-- ThreadPlanCallOnFunctionExit.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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Target/ThreadPlanCallOnFunctionExit.h" 10 11 using namespace lldb; 12 using namespace lldb_private; 13 14 ThreadPlanCallOnFunctionExit::ThreadPlanCallOnFunctionExit( 15 Thread &thread, const Callback &callback) 16 : ThreadPlan(ThreadPlanKind::eKindGeneric, "CallOnFunctionExit", thread, 17 eVoteNoOpinion, eVoteNoOpinion // TODO check with Jim on these 18 ), 19 m_callback(callback) { 20 // We are not a user-generated plan. 21 SetIsMasterPlan(false); 22 } 23 24 void ThreadPlanCallOnFunctionExit::DidPush() { 25 // We now want to queue the "step out" thread plan so it executes and 26 // completes. 27 28 // Set stop vote to eVoteNo. 29 Status status; 30 m_step_out_threadplan_sp = GetThread().QueueThreadPlanForStepOut( 31 false, // abort other plans 32 nullptr, // addr_context 33 true, // first instruction 34 true, // stop other threads 35 eVoteNo, // do not say "we're stopping" 36 eVoteNoOpinion, // don't care about run state broadcasting 37 0, // frame_idx 38 status, // status 39 eLazyBoolCalculate // avoid code w/o debinfo 40 ); 41 } 42 43 // ThreadPlan API 44 45 void ThreadPlanCallOnFunctionExit::GetDescription( 46 Stream *s, lldb::DescriptionLevel level) { 47 if (!s) 48 return; 49 s->Printf("Running until completion of current function, then making " 50 "callback."); 51 } 52 53 bool ThreadPlanCallOnFunctionExit::ValidatePlan(Stream *error) { 54 // We'll say we're always good since I don't know what would make this 55 // invalid. 56 return true; 57 } 58 59 bool ThreadPlanCallOnFunctionExit::ShouldStop(Event *event_ptr) { 60 // If this is where we find out that an internal stop came in, then: Check if 61 // the step-out plan completed. If it did, then we want to run the callback 62 // here (our reason for living...) 63 if (m_step_out_threadplan_sp && m_step_out_threadplan_sp->IsPlanComplete()) { 64 m_callback(); 65 66 // We no longer need the pointer to the step-out thread plan. 67 m_step_out_threadplan_sp.reset(); 68 69 // Indicate that this plan is done and can be discarded. 70 SetPlanComplete(); 71 72 // We're done now, but we want to return false so that we don't cause the 73 // thread to really stop. 74 } 75 76 return false; 77 } 78 79 bool ThreadPlanCallOnFunctionExit::WillStop() { 80 // The code looks like the return value is ignored via ThreadList:: 81 // ShouldStop(). This is called when we really are going to stop. We don't 82 // care and don't need to do anything here. 83 return false; 84 } 85 86 bool ThreadPlanCallOnFunctionExit::DoPlanExplainsStop(Event *event_ptr) { 87 // We don't ever explain a stop. The only stop that is relevant to us 88 // directly is the step_out plan we added to do the heavy lifting of getting 89 // us past the current method. 90 return false; 91 } 92 93 lldb::StateType ThreadPlanCallOnFunctionExit::GetPlanRunState() { 94 // This value doesn't matter - we'll never be the top thread plan, so nobody 95 // will ask us this question. 96 return eStateRunning; 97 } 98