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