1254721Semaste//===-- ThreadPlanStepThrough.cpp -------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste// C Includes 11254721Semaste// C++ Includes 12254721Semaste// Other libraries and framework includes 13254721Semaste// Project includes 14296417Sdim#include "lldb/Target/ThreadPlanStepThrough.h" 15254721Semaste#include "lldb/Core/Log.h" 16254721Semaste#include "lldb/Core/Stream.h" 17254721Semaste#include "lldb/Target/DynamicLoader.h" 18254721Semaste#include "lldb/Target/ObjCLanguageRuntime.h" 19254721Semaste#include "lldb/Target/Process.h" 20254721Semaste#include "lldb/Target/RegisterContext.h" 21254721Semaste#include "lldb/Target/Target.h" 22254721Semaste#include "lldb/Breakpoint/Breakpoint.h" 23254721Semaste 24254721Semasteusing namespace lldb; 25254721Semasteusing namespace lldb_private; 26254721Semaste 27254721Semaste//---------------------------------------------------------------------- 28254721Semaste// ThreadPlanStepThrough: If the current instruction is a trampoline, step through it 29254721Semaste// If it is the beginning of the prologue of a function, step through that as well. 30254721Semaste// FIXME: At present only handles DYLD trampolines. 31254721Semaste//---------------------------------------------------------------------- 32254721Semaste 33254721SemasteThreadPlanStepThrough::ThreadPlanStepThrough (Thread &thread, StackID &m_stack_id, bool stop_others) : 34254721Semaste ThreadPlan (ThreadPlan::eKindStepThrough, "Step through trampolines and prologues", thread, eVoteNoOpinion, eVoteNoOpinion), 35254721Semaste m_start_address (0), 36254721Semaste m_backstop_bkpt_id (LLDB_INVALID_BREAK_ID), 37254721Semaste m_backstop_addr(LLDB_INVALID_ADDRESS), 38254721Semaste m_return_stack_id (m_stack_id), 39254721Semaste m_stop_others (stop_others) 40254721Semaste{ 41254721Semaste LookForPlanToStepThroughFromCurrentPC(); 42254721Semaste 43254721Semaste // If we don't get a valid step through plan, don't bother to set up a backstop. 44254721Semaste if (m_sub_plan_sp) 45254721Semaste { 46254721Semaste m_start_address = GetThread().GetRegisterContext()->GetPC(0); 47254721Semaste 48254721Semaste // We are going to return back to the concrete frame 1, we might pass by some inlined code that we're in 49254721Semaste // the middle of by doing this, but it's easier than trying to figure out where the inlined code might return to. 50254721Semaste 51254721Semaste StackFrameSP return_frame_sp = m_thread.GetFrameWithStackID (m_stack_id); 52254721Semaste 53254721Semaste if (return_frame_sp) 54254721Semaste { 55254721Semaste m_backstop_addr = return_frame_sp->GetFrameCodeAddress().GetLoadAddress(m_thread.CalculateTarget().get()); 56258054Semaste Breakpoint *return_bp = m_thread.GetProcess()->GetTarget().CreateBreakpoint (m_backstop_addr, true, false).get(); 57296417Sdim if (return_bp != nullptr) 58254721Semaste { 59254721Semaste return_bp->SetThreadID(m_thread.GetID()); 60254721Semaste m_backstop_bkpt_id = return_bp->GetID(); 61254721Semaste return_bp->SetBreakpointKind("step-through-backstop"); 62254721Semaste } 63254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 64254721Semaste if (log) 65254721Semaste { 66254721Semaste log->Printf ("Setting backstop breakpoint %d at address: 0x%" PRIx64, m_backstop_bkpt_id, m_backstop_addr); 67254721Semaste } 68254721Semaste } 69254721Semaste } 70254721Semaste} 71254721Semaste 72254721SemasteThreadPlanStepThrough::~ThreadPlanStepThrough () 73254721Semaste{ 74254721Semaste ClearBackstopBreakpoint (); 75254721Semaste} 76254721Semaste 77254721Semastevoid 78254721SemasteThreadPlanStepThrough::DidPush () 79254721Semaste{ 80254721Semaste if (m_sub_plan_sp) 81254721Semaste PushPlan(m_sub_plan_sp); 82254721Semaste} 83254721Semaste 84254721Semastevoid 85254721SemasteThreadPlanStepThrough::LookForPlanToStepThroughFromCurrentPC() 86254721Semaste{ 87280031Sdim DynamicLoader *loader = m_thread.GetProcess()->GetDynamicLoader(); 88280031Sdim if (loader) 89280031Sdim m_sub_plan_sp = loader->GetStepThroughTrampolinePlan (m_thread, m_stop_others); 90280031Sdim 91254721Semaste // If that didn't come up with anything, try the ObjC runtime plugin: 92254721Semaste if (!m_sub_plan_sp.get()) 93254721Semaste { 94254721Semaste ObjCLanguageRuntime *objc_runtime = m_thread.GetProcess()->GetObjCLanguageRuntime(); 95254721Semaste if (objc_runtime) 96254721Semaste m_sub_plan_sp = objc_runtime->GetStepThroughTrampolinePlan (m_thread, m_stop_others); 97254721Semaste } 98254721Semaste 99254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 100254721Semaste if (log) 101254721Semaste { 102254721Semaste lldb::addr_t current_address = GetThread().GetRegisterContext()->GetPC(0); 103254721Semaste if (m_sub_plan_sp) 104254721Semaste { 105254721Semaste StreamString s; 106254721Semaste m_sub_plan_sp->GetDescription(&s, lldb::eDescriptionLevelFull); 107254721Semaste log->Printf ("Found step through plan from 0x%" PRIx64 ": %s", current_address, s.GetData()); 108254721Semaste } 109254721Semaste else 110254721Semaste { 111254721Semaste log->Printf ("Couldn't find step through plan from address 0x%" PRIx64 ".", current_address); 112254721Semaste } 113254721Semaste } 114254721Semaste} 115254721Semaste 116254721Semastevoid 117254721SemasteThreadPlanStepThrough::GetDescription (Stream *s, lldb::DescriptionLevel level) 118254721Semaste{ 119254721Semaste if (level == lldb::eDescriptionLevelBrief) 120254721Semaste s->Printf ("Step through"); 121254721Semaste else 122254721Semaste { 123254721Semaste s->PutCString ("Stepping through trampoline code from: "); 124254721Semaste s->Address(m_start_address, sizeof (addr_t)); 125254721Semaste if (m_backstop_bkpt_id != LLDB_INVALID_BREAK_ID) 126254721Semaste { 127254721Semaste s->Printf (" with backstop breakpoint id: %d at address: ", m_backstop_bkpt_id); 128254721Semaste s->Address (m_backstop_addr, sizeof (addr_t)); 129254721Semaste } 130254721Semaste else 131254721Semaste s->PutCString (" unable to set a backstop breakpoint."); 132254721Semaste } 133254721Semaste} 134254721Semaste 135254721Semastebool 136254721SemasteThreadPlanStepThrough::ValidatePlan (Stream *error) 137254721Semaste{ 138296417Sdim return m_sub_plan_sp.get() != nullptr; 139254721Semaste} 140254721Semaste 141254721Semastebool 142254721SemasteThreadPlanStepThrough::DoPlanExplainsStop (Event *event_ptr) 143254721Semaste{ 144254721Semaste // If we have a sub-plan, it will have been asked first if we explain the stop, and 145254721Semaste // we won't get asked. The only time we would be the one directly asked this question 146254721Semaste // is if we hit our backstop breakpoint. 147254721Semaste 148296417Sdim return HitOurBackstopBreakpoint(); 149254721Semaste} 150254721Semaste 151254721Semastebool 152254721SemasteThreadPlanStepThrough::ShouldStop (Event *event_ptr) 153254721Semaste{ 154254721Semaste // If we've already marked ourselves done, then we're done... 155254721Semaste if (IsPlanComplete()) 156254721Semaste return true; 157254721Semaste 158254721Semaste // First, did we hit the backstop breakpoint? 159254721Semaste if (HitOurBackstopBreakpoint()) 160254721Semaste { 161262528Semaste SetPlanComplete(true); 162254721Semaste return true; 163254721Semaste } 164254721Semaste 165254721Semaste // If we don't have a sub-plan, then we're also done (can't see how we would ever get here 166254721Semaste // without a plan, but just in case. 167254721Semaste 168254721Semaste if (!m_sub_plan_sp) 169254721Semaste { 170254721Semaste SetPlanComplete(); 171254721Semaste return true; 172254721Semaste } 173254721Semaste 174254721Semaste // If the current sub plan is not done, we don't want to stop. Actually, we probably won't 175254721Semaste // ever get here in this state, since we generally won't get asked any questions if out 176254721Semaste // current sub-plan is not done... 177254721Semaste if (!m_sub_plan_sp->IsPlanComplete()) 178254721Semaste return false; 179254721Semaste 180254721Semaste // If our current sub plan failed, then let's just run to our backstop. If we can't do that then just stop. 181254721Semaste if (!m_sub_plan_sp->PlanSucceeded()) 182254721Semaste { 183254721Semaste if (m_backstop_bkpt_id != LLDB_INVALID_BREAK_ID) 184254721Semaste { 185254721Semaste m_sub_plan_sp.reset(); 186254721Semaste return false; 187254721Semaste } 188254721Semaste else 189254721Semaste { 190254721Semaste SetPlanComplete(false); 191254721Semaste return true; 192254721Semaste } 193254721Semaste } 194254721Semaste 195254721Semaste // Next see if there is a specific step through plan at our current pc (these might 196254721Semaste // chain, for instance stepping through a dylib trampoline to the objc dispatch function...) 197254721Semaste LookForPlanToStepThroughFromCurrentPC(); 198254721Semaste if (m_sub_plan_sp) 199254721Semaste { 200254721Semaste PushPlan (m_sub_plan_sp); 201254721Semaste return false; 202254721Semaste } 203254721Semaste else 204254721Semaste { 205254721Semaste SetPlanComplete(); 206254721Semaste return true; 207254721Semaste } 208254721Semaste} 209254721Semaste 210254721Semastebool 211254721SemasteThreadPlanStepThrough::StopOthers () 212254721Semaste{ 213254721Semaste return m_stop_others; 214254721Semaste} 215254721Semaste 216254721SemasteStateType 217254721SemasteThreadPlanStepThrough::GetPlanRunState () 218254721Semaste{ 219254721Semaste return eStateRunning; 220254721Semaste} 221254721Semaste 222254721Semastebool 223254721SemasteThreadPlanStepThrough::DoWillResume (StateType resume_state, bool current_plan) 224254721Semaste{ 225254721Semaste return true; 226254721Semaste} 227254721Semaste 228254721Semastebool 229254721SemasteThreadPlanStepThrough::WillStop () 230254721Semaste{ 231254721Semaste return true; 232254721Semaste} 233254721Semaste 234254721Semastevoid 235254721SemasteThreadPlanStepThrough::ClearBackstopBreakpoint () 236254721Semaste{ 237254721Semaste if (m_backstop_bkpt_id != LLDB_INVALID_BREAK_ID) 238254721Semaste { 239254721Semaste m_thread.GetProcess()->GetTarget().RemoveBreakpointByID (m_backstop_bkpt_id); 240254721Semaste m_backstop_bkpt_id = LLDB_INVALID_BREAK_ID; 241254721Semaste } 242254721Semaste} 243254721Semaste 244254721Semastebool 245254721SemasteThreadPlanStepThrough::MischiefManaged () 246254721Semaste{ 247254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 248254721Semaste 249254721Semaste if (!IsPlanComplete()) 250254721Semaste { 251254721Semaste return false; 252254721Semaste } 253254721Semaste else 254254721Semaste { 255254721Semaste if (log) 256254721Semaste log->Printf("Completed step through step plan."); 257254721Semaste 258254721Semaste ClearBackstopBreakpoint (); 259254721Semaste ThreadPlan::MischiefManaged (); 260254721Semaste return true; 261254721Semaste } 262254721Semaste} 263254721Semaste 264254721Semastebool 265254721SemasteThreadPlanStepThrough::HitOurBackstopBreakpoint() 266254721Semaste{ 267254721Semaste StopInfoSP stop_info_sp(m_thread.GetStopInfo()); 268254721Semaste if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint) 269254721Semaste { 270254721Semaste break_id_t stop_value = (break_id_t) stop_info_sp->GetValue(); 271254721Semaste BreakpointSiteSP cur_site_sp = m_thread.GetProcess()->GetBreakpointSiteList().FindByID(stop_value); 272254721Semaste if (cur_site_sp && cur_site_sp->IsBreakpointAtThisSite(m_backstop_bkpt_id)) 273254721Semaste { 274254721Semaste StackID cur_frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 275254721Semaste 276254721Semaste if (cur_frame_zero_id == m_return_stack_id) 277254721Semaste { 278254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 279254721Semaste if (log) 280254721Semaste log->PutCString ("ThreadPlanStepThrough hit backstop breakpoint."); 281254721Semaste return true; 282254721Semaste } 283254721Semaste } 284254721Semaste } 285254721Semaste return false; 286254721Semaste} 287