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