1 //===-- ThreadPlanStepThrough.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/ThreadPlanStepThrough.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/lldb-private-log.h" 17 #include "lldb/Core/Log.h" 18 #include "lldb/Core/Stream.h" 19 #include "lldb/Target/DynamicLoader.h" 20 #include "lldb/Target/ObjCLanguageRuntime.h" 21 #include "lldb/Target/Process.h" 22 #include "lldb/Target/RegisterContext.h" 23 24 using namespace lldb; 25 using namespace lldb_private; 26 27 //---------------------------------------------------------------------- 28 // ThreadPlanStepThrough: If the current instruction is a trampoline, step through it 29 // If it is the beginning of the prologue of a function, step through that as well. 30 // FIXME: At present only handles DYLD trampolines. 31 //---------------------------------------------------------------------- 32 33 ThreadPlanStepThrough::ThreadPlanStepThrough (Thread &thread, bool stop_others) : 34 ThreadPlan (ThreadPlan::eKindStepThrough, "Step through trampolines and prologues", thread, eVoteNoOpinion, eVoteNoOpinion), 35 m_start_address (0), 36 m_stop_others (stop_others) 37 { 38 m_start_address = GetThread().GetRegisterContext()->GetPC(0); 39 } 40 41 ThreadPlanStepThrough::~ThreadPlanStepThrough () 42 { 43 } 44 45 void 46 ThreadPlanStepThrough::GetDescription (Stream *s, lldb::DescriptionLevel level) 47 { 48 if (level == lldb::eDescriptionLevelBrief) 49 s->Printf ("Step through"); 50 else 51 { 52 s->Printf ("Stepping through trampoline code from: "); 53 s->Address(m_start_address, sizeof (addr_t)); 54 } 55 } 56 57 bool 58 ThreadPlanStepThrough::ValidatePlan (Stream *error) 59 { 60 if (HappyToStopHere()) 61 return false; 62 else 63 return true; 64 } 65 66 bool 67 ThreadPlanStepThrough::PlanExplainsStop () 68 { 69 return true; 70 } 71 72 bool 73 ThreadPlanStepThrough::ShouldStop (Event *event_ptr) 74 { 75 return true; 76 } 77 78 bool 79 ThreadPlanStepThrough::StopOthers () 80 { 81 return m_stop_others; 82 } 83 84 StateType 85 ThreadPlanStepThrough::GetPlanRunState () 86 { 87 return eStateStepping; 88 } 89 90 bool 91 ThreadPlanStepThrough::WillResume (StateType resume_state, bool current_plan) 92 { 93 ThreadPlan::WillResume(resume_state, current_plan); 94 if (current_plan) 95 { 96 ThreadPlanSP sub_plan_sp(m_thread.GetProcess().GetDynamicLoader()->GetStepThroughTrampolinePlan (m_thread, m_stop_others)); 97 // If that didn't come up with anything, try the ObjC runtime plugin: 98 if (sub_plan_sp == NULL) 99 { 100 ObjCLanguageRuntime *objc_runtime = m_thread.GetProcess().GetObjCLanguageRuntime(); 101 if (objc_runtime) 102 sub_plan_sp = objc_runtime->GetStepThroughTrampolinePlan (m_thread, m_stop_others); 103 } 104 105 if (sub_plan_sp != NULL) 106 PushPlan (sub_plan_sp); 107 } 108 return true; 109 } 110 111 bool 112 ThreadPlanStepThrough::WillStop () 113 { 114 return true; 115 } 116 117 bool 118 ThreadPlanStepThrough::MischiefManaged () 119 { 120 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 121 122 // Stop if we're happy with the place we've landed... 123 124 if (!HappyToStopHere()) 125 { 126 // If we are still at the PC we were trying to step over. 127 return false; 128 } 129 else 130 { 131 if (log) 132 log->Printf("Completed step through step plan."); 133 ThreadPlan::MischiefManaged (); 134 return true; 135 } 136 } 137 138 bool 139 ThreadPlanStepThrough::HappyToStopHere() 140 { 141 // This should again ask the various trampolines whether we are still at a 142 // trampoline point, and if so, continue through the possibly nested trampolines. 143 144 return true; 145 } 146 147