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 and 27 // completes. 28 29 // Set stop vote to eVoteNo. 30 Status status; 31 m_step_out_threadplan_sp = GetThread().QueueThreadPlanForStepOut( 32 false, // abort other plans 33 nullptr, // addr_context 34 true, // first instruction 35 true, // stop other threads 36 eVoteNo, // do not say "we're stopping" 37 eVoteNoOpinion, // don't care about run state broadcasting 38 0, // frame_idx 39 status, // status 40 eLazyBoolCalculate // avoid code w/o debinfo 41 ); 42 } 43 44 // ------------------------------------------------------------------------- 45 // ThreadPlan API 46 // ------------------------------------------------------------------------- 47 48 void ThreadPlanCallOnFunctionExit::GetDescription( 49 Stream *s, lldb::DescriptionLevel level) { 50 if (!s) 51 return; 52 s->Printf("Running until completion of current function, then making " 53 "callback."); 54 } 55 56 bool ThreadPlanCallOnFunctionExit::ValidatePlan(Stream *error) { 57 // We'll say we're always good since I don't know what would make this 58 // invalid. 59 return true; 60 } 61 62 bool ThreadPlanCallOnFunctionExit::ShouldStop(Event *event_ptr) { 63 // If this is where we find out that an internal stop came in, then: Check if 64 // the step-out plan completed. If it did, then we want to run the callback 65 // here (our reason for living...) 66 if (m_step_out_threadplan_sp && m_step_out_threadplan_sp->IsPlanComplete()) { 67 m_callback(); 68 69 // We no longer need the pointer to the step-out thread plan. 70 m_step_out_threadplan_sp.reset(); 71 72 // Indicate that this plan is done and can be discarded. 73 SetPlanComplete(); 74 75 // We're done now, but we want to return false so that we don't cause the 76 // thread to really stop. 77 } 78 79 return false; 80 } 81 82 bool ThreadPlanCallOnFunctionExit::WillStop() { 83 // The code looks like the return value is ignored via ThreadList:: 84 // ShouldStop(). This is called when we really are going to stop. We don't 85 // care 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 to us 91 // directly is the step_out plan we added to do the heavy lifting of getting 92 // 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 nobody 98 // will ask us this question. 99 return eStateRunning; 100 } 101