130fdc8d8SChris Lattner //===-- ThreadPlanStepInRange.cpp -------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepInRange.h" 1130fdc8d8SChris Lattner 1230fdc8d8SChris Lattner // C Includes 1330fdc8d8SChris Lattner // C++ Includes 1430fdc8d8SChris Lattner // Other libraries and framework includes 1530fdc8d8SChris Lattner // Project includes 1630fdc8d8SChris Lattner 1730fdc8d8SChris Lattner #include "lldb/lldb-private-log.h" 1830fdc8d8SChris Lattner #include "lldb/Core/Log.h" 1930fdc8d8SChris Lattner #include "lldb/Core/Stream.h" 20a56c8006SJim Ingham #include "lldb/Symbol/Symbol.h" 217ce490c6SJim Ingham #include "lldb/Symbol/Function.h" 2230fdc8d8SChris Lattner #include "lldb/Target/Process.h" 2330fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h" 24514487e8SGreg Clayton #include "lldb/Target/Target.h" 2530fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 2630fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepOut.h" 2730fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepThrough.h" 28a56c8006SJim Ingham #include "lldb/Core/RegularExpression.h" 2930fdc8d8SChris Lattner 3030fdc8d8SChris Lattner using namespace lldb; 3130fdc8d8SChris Lattner using namespace lldb_private; 3230fdc8d8SChris Lattner 3330fdc8d8SChris Lattner uint32_t ThreadPlanStepInRange::s_default_flag_values = ThreadPlanShouldStopHere::eAvoidNoDebug; 3430fdc8d8SChris Lattner 3530fdc8d8SChris Lattner //---------------------------------------------------------------------- 3630fdc8d8SChris Lattner // ThreadPlanStepInRange: Step through a stack range, either stepping over or into 3730fdc8d8SChris Lattner // based on the value of \a type. 3830fdc8d8SChris Lattner //---------------------------------------------------------------------- 3930fdc8d8SChris Lattner 4030fdc8d8SChris Lattner ThreadPlanStepInRange::ThreadPlanStepInRange 4130fdc8d8SChris Lattner ( 4230fdc8d8SChris Lattner Thread &thread, 4330fdc8d8SChris Lattner const AddressRange &range, 4430fdc8d8SChris Lattner const SymbolContext &addr_context, 4530fdc8d8SChris Lattner lldb::RunMode stop_others 4630fdc8d8SChris Lattner ) : 47b01e742aSJim Ingham ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others), 487ce490c6SJim Ingham ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL), 49*f02a2e96SJim Ingham m_step_past_prologue (true), 50*f02a2e96SJim Ingham m_virtual_step (false) 5130fdc8d8SChris Lattner { 5230fdc8d8SChris Lattner SetFlagsToDefault (); 5330fdc8d8SChris Lattner } 5430fdc8d8SChris Lattner 5530fdc8d8SChris Lattner ThreadPlanStepInRange::~ThreadPlanStepInRange () 5630fdc8d8SChris Lattner { 5730fdc8d8SChris Lattner } 5830fdc8d8SChris Lattner 5930fdc8d8SChris Lattner void 6030fdc8d8SChris Lattner ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level) 6130fdc8d8SChris Lattner { 6230fdc8d8SChris Lattner if (level == lldb::eDescriptionLevelBrief) 6330fdc8d8SChris Lattner s->Printf("step in"); 6430fdc8d8SChris Lattner else 6530fdc8d8SChris Lattner { 6630fdc8d8SChris Lattner s->Printf ("Stepping through range (stepping into functions): "); 67c4c9fedcSJim Ingham DumpRanges(s); 6830fdc8d8SChris Lattner } 6930fdc8d8SChris Lattner } 7030fdc8d8SChris Lattner 7130fdc8d8SChris Lattner bool 7230fdc8d8SChris Lattner ThreadPlanStepInRange::ShouldStop (Event *event_ptr) 7330fdc8d8SChris Lattner { 742d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 7530fdc8d8SChris Lattner m_no_more_plans = false; 7630fdc8d8SChris Lattner 7730fdc8d8SChris Lattner if (log) 7830fdc8d8SChris Lattner { 7930fdc8d8SChris Lattner StreamString s; 80514487e8SGreg Clayton s.Address (m_thread.GetRegisterContext()->GetPC(), 811ac04c30SGreg Clayton m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize()); 8230fdc8d8SChris Lattner log->Printf("ThreadPlanStepInRange reached %s.", s.GetData()); 8330fdc8d8SChris Lattner } 8430fdc8d8SChris Lattner 8525f66700SJim Ingham if (IsPlanComplete()) 8625f66700SJim Ingham return true; 8725f66700SJim Ingham 8830fdc8d8SChris Lattner ThreadPlan* new_plan = NULL; 8930fdc8d8SChris Lattner 90*f02a2e96SJim Ingham if (m_virtual_step) 91*f02a2e96SJim Ingham { 92*f02a2e96SJim Ingham // If we've just completed a virtual step, all we need to do is check for a ShouldStopHere plan, and otherwise 93*f02a2e96SJim Ingham // we're done. 94*f02a2e96SJim Ingham new_plan = InvokeShouldStopHereCallback(); 95*f02a2e96SJim Ingham } 96*f02a2e96SJim Ingham else 97*f02a2e96SJim Ingham { 989d790c5dSJim Ingham // Stepping through should be done stopping other threads in general, since we're setting a breakpoint and 999d790c5dSJim Ingham // continuing... 1009d790c5dSJim Ingham 10130fdc8d8SChris Lattner bool stop_others; 1029d790c5dSJim Ingham if (m_stop_others != lldb::eAllThreads) 10330fdc8d8SChris Lattner stop_others = true; 10430fdc8d8SChris Lattner else 10530fdc8d8SChris Lattner stop_others = false; 10630fdc8d8SChris Lattner 107b5c0d1ccSJim Ingham FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 108b5c0d1ccSJim Ingham 109b5c0d1ccSJim Ingham if (frame_order == eFrameCompareOlder) 1105822173bSJim Ingham { 1115822173bSJim Ingham // If we're in an older frame then we should stop. 1125822173bSJim Ingham // 1135822173bSJim Ingham // A caveat to this is if we think the frame is older but we're actually in a trampoline. 1145822173bSJim Ingham // I'm going to make the assumption that you wouldn't RETURN to a trampoline. So if we are 1155822173bSJim Ingham // in a trampoline we think the frame is older because the trampoline confused the backtracer. 11618de2fdcSJim Ingham new_plan = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); 1175822173bSJim Ingham if (new_plan == NULL) 1185822173bSJim Ingham return true; 1195822173bSJim Ingham else if (log) 1205822173bSJim Ingham { 1215822173bSJim Ingham log->Printf("Thought I stepped out, but in fact arrived at a trampoline."); 1225822173bSJim Ingham } 1235822173bSJim Ingham 1245822173bSJim Ingham } 125564d8bc2SJim Ingham else if (frame_order == eFrameCompareEqual && InSymbol()) 1265822173bSJim Ingham { 1275822173bSJim Ingham // If we are not in a place we should step through, we're done. 1285822173bSJim Ingham // One tricky bit here is that some stubs don't push a frame, so we have to check 1295822173bSJim Ingham // both the case of a frame that is younger, or the same as this frame. 1305822173bSJim Ingham // However, if the frame is the same, and we are still in the symbol we started 1315822173bSJim Ingham // in, the we don't need to do this. This first check isn't strictly necessary, 1325822173bSJim Ingham // but it is more efficient. 1335822173bSJim Ingham 134564d8bc2SJim Ingham // If we're still in the range, keep going, either by running to the next branch breakpoint, or by 135564d8bc2SJim Ingham // stepping. 136564d8bc2SJim Ingham if (InRange()) 137564d8bc2SJim Ingham { 138564d8bc2SJim Ingham SetNextBranchBreakpoint(); 139564d8bc2SJim Ingham return false; 140564d8bc2SJim Ingham } 141564d8bc2SJim Ingham 1425822173bSJim Ingham SetPlanComplete(); 1435822173bSJim Ingham return true; 1445822173bSJim Ingham } 1455822173bSJim Ingham 146564d8bc2SJim Ingham // If we get to this point, we're not going to use a previously set "next branch" breakpoint, so delete it: 147564d8bc2SJim Ingham ClearNextBranchBreakpoint(); 148564d8bc2SJim Ingham 1495822173bSJim Ingham // We may have set the plan up above in the FrameIsOlder section: 1505822173bSJim Ingham 1515822173bSJim Ingham if (new_plan == NULL) 15218de2fdcSJim Ingham new_plan = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); 15308b87e0dSJim Ingham 15408b87e0dSJim Ingham if (log) 15508b87e0dSJim Ingham { 15608b87e0dSJim Ingham if (new_plan != NULL) 15708b87e0dSJim Ingham log->Printf ("Found a step through plan: %s", new_plan->GetName()); 15808b87e0dSJim Ingham else 15908b87e0dSJim Ingham log->Printf ("No step through plan found."); 16008b87e0dSJim Ingham } 16108b87e0dSJim Ingham 16230fdc8d8SChris Lattner // If not, give the "should_stop" callback a chance to push a plan to get us out of here. 16330fdc8d8SChris Lattner // But only do that if we actually have stepped in. 164b5c0d1ccSJim Ingham if (!new_plan && frame_order == eFrameCompareYounger) 16530fdc8d8SChris Lattner new_plan = InvokeShouldStopHereCallback(); 16630fdc8d8SChris Lattner 1677ce490c6SJim Ingham // If we've stepped in and we are going to stop here, check to see if we were asked to 1687ce490c6SJim Ingham // run past the prologue, and if so do that. 1697ce490c6SJim Ingham 170b5c0d1ccSJim Ingham if (new_plan == NULL && frame_order == eFrameCompareYounger && m_step_past_prologue) 1717ce490c6SJim Ingham { 1727ce490c6SJim Ingham lldb::StackFrameSP curr_frame = m_thread.GetStackFrameAtIndex(0); 1737ce490c6SJim Ingham if (curr_frame) 1747ce490c6SJim Ingham { 1757ce490c6SJim Ingham size_t bytes_to_skip = 0; 1767ce490c6SJim Ingham lldb::addr_t curr_addr = m_thread.GetRegisterContext()->GetPC(); 1777ce490c6SJim Ingham Address func_start_address; 1787ce490c6SJim Ingham 1797ce490c6SJim Ingham SymbolContext sc = curr_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextSymbol); 1807ce490c6SJim Ingham 1817ce490c6SJim Ingham if (sc.function) 1827ce490c6SJim Ingham { 1837ce490c6SJim Ingham func_start_address = sc.function->GetAddressRange().GetBaseAddress(); 184d9e416c0SGreg Clayton if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) 1857ce490c6SJim Ingham bytes_to_skip = sc.function->GetPrologueByteSize(); 1867ce490c6SJim Ingham } 1877ce490c6SJim Ingham else if (sc.symbol) 1887ce490c6SJim Ingham { 189e7612134SGreg Clayton func_start_address = sc.symbol->GetAddress(); 190d9e416c0SGreg Clayton if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) 1917ce490c6SJim Ingham bytes_to_skip = sc.symbol->GetPrologueByteSize(); 1927ce490c6SJim Ingham } 1937ce490c6SJim Ingham 1947ce490c6SJim Ingham if (bytes_to_skip != 0) 1957ce490c6SJim Ingham { 1967ce490c6SJim Ingham func_start_address.Slide (bytes_to_skip); 19720ad3c40SCaroline Tice log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 1987ce490c6SJim Ingham if (log) 1997ce490c6SJim Ingham log->Printf ("Pushing past prologue "); 2007ce490c6SJim Ingham 2017ce490c6SJim Ingham new_plan = m_thread.QueueThreadPlanForRunToAddress(false, func_start_address,true); 2027ce490c6SJim Ingham } 2037ce490c6SJim Ingham } 2047ce490c6SJim Ingham } 205*f02a2e96SJim Ingham } 2067ce490c6SJim Ingham 20730fdc8d8SChris Lattner if (new_plan == NULL) 20830fdc8d8SChris Lattner { 20930fdc8d8SChris Lattner m_no_more_plans = true; 21030fdc8d8SChris Lattner SetPlanComplete(); 21130fdc8d8SChris Lattner return true; 21230fdc8d8SChris Lattner } 21330fdc8d8SChris Lattner else 21430fdc8d8SChris Lattner { 21530fdc8d8SChris Lattner m_no_more_plans = false; 21630fdc8d8SChris Lattner return false; 21730fdc8d8SChris Lattner } 21830fdc8d8SChris Lattner } 21930fdc8d8SChris Lattner 22030fdc8d8SChris Lattner void 22130fdc8d8SChris Lattner ThreadPlanStepInRange::SetFlagsToDefault () 22230fdc8d8SChris Lattner { 22330fdc8d8SChris Lattner GetFlags().Set(ThreadPlanStepInRange::s_default_flag_values); 22430fdc8d8SChris Lattner } 22530fdc8d8SChris Lattner 22630fdc8d8SChris Lattner void 227a56c8006SJim Ingham ThreadPlanStepInRange::SetAvoidRegexp(const char *name) 228a56c8006SJim Ingham { 229a56c8006SJim Ingham if (m_avoid_regexp_ap.get() == NULL) 230a56c8006SJim Ingham m_avoid_regexp_ap.reset (new RegularExpression(name)); 231a56c8006SJim Ingham 232a56c8006SJim Ingham m_avoid_regexp_ap->Compile (name); 233a56c8006SJim Ingham } 234a56c8006SJim Ingham 235a56c8006SJim Ingham void 23630fdc8d8SChris Lattner ThreadPlanStepInRange::SetDefaultFlagValue (uint32_t new_value) 23730fdc8d8SChris Lattner { 23830fdc8d8SChris Lattner // TODO: Should we test this for sanity? 23930fdc8d8SChris Lattner ThreadPlanStepInRange::s_default_flag_values = new_value; 24030fdc8d8SChris Lattner } 24130fdc8d8SChris Lattner 242a56c8006SJim Ingham bool 243a56c8006SJim Ingham ThreadPlanStepInRange::FrameMatchesAvoidRegexp () 244a56c8006SJim Ingham { 245a56c8006SJim Ingham StackFrame *frame = GetThread().GetStackFrameAtIndex(0).get(); 246a56c8006SJim Ingham 24767cc0636SGreg Clayton const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get(); 248ee8aea10SJim Ingham if (avoid_regexp_to_use == NULL) 249ee8aea10SJim Ingham avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp(); 250ee8aea10SJim Ingham 251ee8aea10SJim Ingham if (avoid_regexp_to_use != NULL) 252a56c8006SJim Ingham { 2534592cbc4SGreg Clayton SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol); 254a56c8006SJim Ingham if (sc.symbol != NULL) 255a56c8006SJim Ingham { 2564592cbc4SGreg Clayton const char *frame_function_name = sc.GetFunctionName().GetCString(); 2574592cbc4SGreg Clayton if (frame_function_name) 2584592cbc4SGreg Clayton return avoid_regexp_to_use->Execute(frame_function_name); 259a56c8006SJim Ingham } 260a56c8006SJim Ingham } 261a56c8006SJim Ingham return false; 262a56c8006SJim Ingham } 263a56c8006SJim Ingham 26430fdc8d8SChris Lattner ThreadPlan * 26530fdc8d8SChris Lattner ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton) 26630fdc8d8SChris Lattner { 267a56c8006SJim Ingham bool should_step_out = false; 26830fdc8d8SChris Lattner StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get(); 26930fdc8d8SChris Lattner 27073b472d4SGreg Clayton if (flags.Test(eAvoidNoDebug)) 271a56c8006SJim Ingham { 27230fdc8d8SChris Lattner if (!frame->HasDebugInformation()) 273af0f1759SJim Ingham { 274513c6bb8SJim Ingham LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 275af0f1759SJim Ingham if (log) 276af0f1759SJim Ingham log->Printf ("Stepping out of frame with no debug info"); 277af0f1759SJim Ingham 278a56c8006SJim Ingham should_step_out = true; 279a56c8006SJim Ingham } 280af0f1759SJim Ingham } 281a56c8006SJim Ingham 282a56c8006SJim Ingham if (!should_step_out) 283a56c8006SJim Ingham { 284a56c8006SJim Ingham if (current_plan->GetKind() == eKindStepInRange) 285a56c8006SJim Ingham { 286a56c8006SJim Ingham ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan); 287a56c8006SJim Ingham should_step_out = step_in_range_plan->FrameMatchesAvoidRegexp (); 288a56c8006SJim Ingham } 289a56c8006SJim Ingham } 290a56c8006SJim Ingham 291a56c8006SJim Ingham if (should_step_out) 29230fdc8d8SChris Lattner { 29330fdc8d8SChris Lattner // FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions. 294481cef25SGreg Clayton return current_plan->GetThread().QueueThreadPlanForStepOut (false, 295481cef25SGreg Clayton NULL, 296481cef25SGreg Clayton true, 297a56c8006SJim Ingham current_plan->StopOthers(), 298481cef25SGreg Clayton eVoteNo, 299481cef25SGreg Clayton eVoteNoOpinion, 300481cef25SGreg Clayton 0); // Frame index 30130fdc8d8SChris Lattner } 30230fdc8d8SChris Lattner 30330fdc8d8SChris Lattner return NULL; 30430fdc8d8SChris Lattner } 305fbbfe6ecSJim Ingham 306fbbfe6ecSJim Ingham bool 307fbbfe6ecSJim Ingham ThreadPlanStepInRange::PlanExplainsStop () 308fbbfe6ecSJim Ingham { 309fbbfe6ecSJim Ingham // We always explain a stop. Either we've just done a single step, in which 310fbbfe6ecSJim Ingham // case we'll do our ordinary processing, or we stopped for some 311fbbfe6ecSJim Ingham // reason that isn't handled by our sub-plans, in which case we want to just stop right 312fbbfe6ecSJim Ingham // away. 313fbbfe6ecSJim Ingham // We also set ourselves complete when we stop for this sort of unintended reason, but mark 314fbbfe6ecSJim Ingham // success as false so we don't end up being the reason for the stop. 315fbbfe6ecSJim Ingham // 316fbbfe6ecSJim Ingham // The only variation is that if we are doing "step by running to next branch" in which case 317fbbfe6ecSJim Ingham // if we hit our branch breakpoint we don't set the plan to complete. 318fbbfe6ecSJim Ingham 319*f02a2e96SJim Ingham if (m_virtual_step) 320*f02a2e96SJim Ingham return true; 321*f02a2e96SJim Ingham 322fbbfe6ecSJim Ingham StopInfoSP stop_info_sp = GetPrivateStopReason(); 323fbbfe6ecSJim Ingham if (stop_info_sp) 324fbbfe6ecSJim Ingham { 325fbbfe6ecSJim Ingham StopReason reason = stop_info_sp->GetStopReason(); 326fbbfe6ecSJim Ingham 327fbbfe6ecSJim Ingham switch (reason) 328fbbfe6ecSJim Ingham { 329fbbfe6ecSJim Ingham case eStopReasonBreakpoint: 330fbbfe6ecSJim Ingham if (NextRangeBreakpointExplainsStop(stop_info_sp)) 331fbbfe6ecSJim Ingham return true; 332fbbfe6ecSJim Ingham case eStopReasonWatchpoint: 333fbbfe6ecSJim Ingham case eStopReasonSignal: 334fbbfe6ecSJim Ingham case eStopReasonException: 335513c6bb8SJim Ingham { 336513c6bb8SJim Ingham LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 337fbbfe6ecSJim Ingham if (log) 338fbbfe6ecSJim Ingham log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step."); 339fbbfe6ecSJim Ingham SetPlanComplete(false); 340513c6bb8SJim Ingham } 341fbbfe6ecSJim Ingham break; 342fbbfe6ecSJim Ingham default: 343fbbfe6ecSJim Ingham break; 344fbbfe6ecSJim Ingham } 345fbbfe6ecSJim Ingham } 346fbbfe6ecSJim Ingham return true; 347fbbfe6ecSJim Ingham } 348513c6bb8SJim Ingham 349513c6bb8SJim Ingham bool 350513c6bb8SJim Ingham ThreadPlanStepInRange::WillResume (lldb::StateType resume_state, bool current_plan) 351513c6bb8SJim Ingham { 352513c6bb8SJim Ingham if (resume_state == eStateStepping && current_plan) 353513c6bb8SJim Ingham { 354513c6bb8SJim Ingham // See if we are about to step over a virtual inlined call. 355513c6bb8SJim Ingham bool step_without_resume = m_thread.DecrementCurrentInlinedDepth(); 356513c6bb8SJim Ingham if (step_without_resume) 357513c6bb8SJim Ingham { 358513c6bb8SJim Ingham LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 359513c6bb8SJim Ingham if (log) 360513c6bb8SJim Ingham log->Printf ("ThreadPlanStepInRange::WillResume: returning false, inline_depth: %d", 361513c6bb8SJim Ingham m_thread.GetCurrentInlinedDepth()); 362513c6bb8SJim Ingham SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread)); 363*f02a2e96SJim Ingham 364*f02a2e96SJim Ingham // FIXME: Maybe it would be better to create a InlineStep stop reason, but then 365*f02a2e96SJim Ingham // the whole rest of the world would have to handle that stop reason. 366*f02a2e96SJim Ingham m_virtual_step = true; 367513c6bb8SJim Ingham } 368513c6bb8SJim Ingham return !step_without_resume; 369513c6bb8SJim Ingham } 370513c6bb8SJim Ingham else 371513c6bb8SJim Ingham return ThreadPlan::WillResume(resume_state, current_plan); 372513c6bb8SJim Ingham 373513c6bb8SJim Ingham } 374