1 //===-- ThreadPlanStepRange.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/ThreadPlanStepRange.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 17 #include "lldb/lldb-private-log.h" 18 #include "lldb/Core/Disassembler.h" 19 #include "lldb/Core/Log.h" 20 #include "lldb/Core/Stream.h" 21 #include "lldb/Symbol/Function.h" 22 #include "lldb/Symbol/Symbol.h" 23 #include "lldb/Target/ExecutionContext.h" 24 #include "lldb/Target/Process.h" 25 #include "lldb/Target/RegisterContext.h" 26 #include "lldb/Target/StopInfo.h" 27 #include "lldb/Target/Target.h" 28 #include "lldb/Target/Thread.h" 29 #include "lldb/Target/ThreadPlanRunToAddress.h" 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 35 //---------------------------------------------------------------------- 36 // ThreadPlanStepRange: Step through a stack range, either stepping over or into 37 // based on the value of \a type. 38 //---------------------------------------------------------------------- 39 40 ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind, 41 const char *name, 42 Thread &thread, 43 const AddressRange &range, 44 const SymbolContext &addr_context, 45 lldb::RunMode stop_others) : 46 ThreadPlan (kind, name, thread, eVoteNoOpinion, eVoteNoOpinion), 47 m_addr_context (addr_context), 48 m_address_ranges (), 49 m_stop_others (stop_others), 50 m_stack_id (), 51 m_no_more_plans (false), 52 m_first_run_event (true) 53 { 54 AddRange(range); 55 m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 56 } 57 58 ThreadPlanStepRange::~ThreadPlanStepRange () 59 { 60 ClearNextBranchBreakpoint(); 61 } 62 63 void 64 ThreadPlanStepRange::DidPush () 65 { 66 // See if we can find a "next range" breakpoint: 67 SetNextBranchBreakpoint(); 68 } 69 70 bool 71 ThreadPlanStepRange::ValidatePlan (Stream *error) 72 { 73 return true; 74 } 75 76 Vote 77 ThreadPlanStepRange::ShouldReportStop (Event *event_ptr) 78 { 79 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 80 81 const Vote vote = IsPlanComplete() ? eVoteYes : eVoteNo; 82 if (log) 83 log->Printf ("ThreadPlanStepRange::ShouldReportStop() returning vote %i\n", vote); 84 return vote; 85 } 86 87 void 88 ThreadPlanStepRange::AddRange(const AddressRange &new_range) 89 { 90 // For now I'm just adding the ranges. At some point we may want to 91 // condense the ranges if they overlap, though I don't think it is likely 92 // to be very important. 93 m_address_ranges.push_back (new_range); 94 m_instruction_ranges.push_back (DisassemblerSP()); 95 } 96 97 void 98 ThreadPlanStepRange::DumpRanges(Stream *s) 99 { 100 size_t num_ranges = m_address_ranges.size(); 101 if (num_ranges == 1) 102 { 103 m_address_ranges[0].Dump (s, m_thread.CalculateTarget().get(), Address::DumpStyleLoadAddress); 104 } 105 else 106 { 107 for (size_t i = 0; i < num_ranges; i++) 108 { 109 s->PutCString("%d: "); 110 m_address_ranges[i].Dump (s, m_thread.CalculateTarget().get(), Address::DumpStyleLoadAddress); 111 } 112 } 113 } 114 115 bool 116 ThreadPlanStepRange::InRange () 117 { 118 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 119 bool ret_value = false; 120 121 lldb::addr_t pc_load_addr = m_thread.GetRegisterContext()->GetPC(); 122 123 size_t num_ranges = m_address_ranges.size(); 124 for (size_t i = 0; i < num_ranges; i++) 125 { 126 ret_value = m_address_ranges[i].ContainsLoadAddress(pc_load_addr, m_thread.CalculateTarget().get()); 127 if (ret_value) 128 break; 129 } 130 131 if (!ret_value) 132 { 133 // See if we've just stepped to another part of the same line number... 134 StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get(); 135 136 SymbolContext new_context(frame->GetSymbolContext(eSymbolContextEverything)); 137 if (m_addr_context.line_entry.IsValid() && new_context.line_entry.IsValid()) 138 { 139 if (m_addr_context.line_entry.file == new_context.line_entry.file) 140 { 141 if (m_addr_context.line_entry.line == new_context.line_entry.line) 142 { 143 m_addr_context = new_context; 144 AddRange(m_addr_context.line_entry.range); 145 ret_value = true; 146 if (log) 147 { 148 StreamString s; 149 m_addr_context.line_entry.range.Dump (&s, 150 m_thread.CalculateTarget().get(), 151 Address::DumpStyleLoadAddress); 152 153 log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData()); 154 } 155 } 156 else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress(m_thread.CalculateTarget().get()) 157 != pc_load_addr) 158 { 159 // Another thing that sometimes happens here is that we step out of one line into the MIDDLE of another 160 // line. So far I mostly see this due to bugs in the debug information. 161 // But we probably don't want to be in the middle of a line range, so in that case reset the stepping 162 // range to the line we've stepped into the middle of and continue. 163 m_addr_context = new_context; 164 m_address_ranges.clear(); 165 AddRange(m_addr_context.line_entry.range); 166 ret_value = true; 167 if (log) 168 { 169 StreamString s; 170 m_addr_context.line_entry.range.Dump (&s, 171 m_thread.CalculateTarget().get(), 172 Address::DumpStyleLoadAddress); 173 174 log->Printf ("Step range plan stepped to the middle of new line(%d): %s, continuing to clear this line.", 175 new_context.line_entry.line, 176 s.GetData()); 177 } 178 179 } 180 } 181 182 } 183 184 } 185 186 if (!ret_value && log) 187 log->Printf ("Step range plan out of range to 0x%llx", pc_load_addr); 188 189 return ret_value; 190 } 191 192 bool 193 ThreadPlanStepRange::InSymbol() 194 { 195 lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC(); 196 if (m_addr_context.function != NULL) 197 { 198 return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, m_thread.CalculateTarget().get()); 199 } 200 else if (m_addr_context.symbol) 201 { 202 AddressRange range(m_addr_context.symbol->GetAddress(), m_addr_context.symbol->GetByteSize()); 203 return range.ContainsLoadAddress (cur_pc, m_thread.CalculateTarget().get()); 204 } 205 return false; 206 } 207 208 // FIXME: This should also handle inlining if we aren't going to do inlining in the 209 // main stack. 210 // 211 // Ideally we should remember the whole stack frame list, and then compare that 212 // to the current list. 213 214 lldb::FrameComparison 215 ThreadPlanStepRange::CompareCurrentFrameToStartFrame() 216 { 217 FrameComparison frame_order; 218 219 StackID cur_frame_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 220 221 if (cur_frame_id == m_stack_id) 222 { 223 frame_order = eFrameCompareEqual; 224 } 225 else if (cur_frame_id < m_stack_id) 226 { 227 frame_order = eFrameCompareYounger; 228 } 229 else 230 { 231 frame_order = eFrameCompareOlder; 232 } 233 return frame_order; 234 } 235 236 bool 237 ThreadPlanStepRange::StopOthers () 238 { 239 if (m_stop_others == lldb::eOnlyThisThread 240 || m_stop_others == lldb::eOnlyDuringStepping) 241 return true; 242 else 243 return false; 244 } 245 246 InstructionList * 247 ThreadPlanStepRange::GetInstructionsForAddress(lldb::addr_t addr, size_t &range_index, size_t &insn_offset) 248 { 249 size_t num_ranges = m_address_ranges.size(); 250 for (size_t i = 0; i < num_ranges; i++) 251 { 252 if (m_address_ranges[i].ContainsLoadAddress(addr, &GetTarget())) 253 { 254 // Some joker added a zero size range to the stepping range... 255 if (m_address_ranges[i].GetByteSize() == 0) 256 return NULL; 257 258 if (!m_instruction_ranges[i]) 259 { 260 //Disassemble the address range given: 261 ExecutionContext exe_ctx (m_thread.GetProcess()); 262 m_instruction_ranges[i] = Disassembler::DisassembleRange(GetTarget().GetArchitecture(), 263 NULL, 264 exe_ctx, 265 m_address_ranges[i]); 266 267 } 268 if (!m_instruction_ranges[i]) 269 return NULL; 270 else 271 { 272 // Find where we are in the instruction list as well. If we aren't at an instruction, 273 // return NULL. In this case, we're probably lost, and shouldn't try to do anything fancy. 274 275 insn_offset = m_instruction_ranges[i]->GetInstructionList().GetIndexOfInstructionAtLoadAddress(addr, GetTarget()); 276 if (insn_offset == UINT32_MAX) 277 return NULL; 278 else 279 { 280 range_index = i; 281 return &m_instruction_ranges[i]->GetInstructionList(); 282 } 283 } 284 } 285 } 286 return NULL; 287 } 288 289 void 290 ThreadPlanStepRange::ClearNextBranchBreakpoint() 291 { 292 if (m_next_branch_bp_sp) 293 { 294 GetTarget().RemoveBreakpointByID (m_next_branch_bp_sp->GetID()); 295 m_next_branch_bp_sp.reset(); 296 } 297 } 298 299 bool 300 ThreadPlanStepRange::SetNextBranchBreakpoint () 301 { 302 // Stepping through ranges using breakpoints doesn't work yet, but with this off we fall back to instruction 303 // single stepping. 304 return false; 305 // Always clear the next branch breakpoint, we don't want to leave one of these stranded. 306 ClearNextBranchBreakpoint(); 307 lldb::addr_t cur_addr = GetThread().GetRegisterContext()->GetPC(); 308 // Find the current address in our address ranges, and fetch the disassembly if we haven't already: 309 size_t pc_index; 310 size_t range_index; 311 InstructionList *instructions = GetInstructionsForAddress (cur_addr, range_index, pc_index); 312 if (instructions == NULL) 313 return false; 314 else 315 { 316 uint32_t branch_index; 317 branch_index = instructions->GetIndexOfNextBranchInstruction (pc_index); 318 319 Address run_to_address; 320 321 // If we didn't find a branch, run to the end of the range. 322 if (branch_index == UINT32_MAX) 323 { 324 branch_index = instructions->GetSize() - 2; 325 } 326 if (branch_index - pc_index > 1) 327 { 328 const bool is_internal = true; 329 run_to_address = instructions->GetInstructionAtIndex(branch_index)->GetAddress(); 330 m_next_branch_bp_sp = GetTarget().CreateBreakpoint(run_to_address, is_internal); 331 m_next_branch_bp_sp->SetThreadID(m_thread.GetID()); 332 return true; 333 } 334 } 335 return false; 336 } 337 338 bool 339 ThreadPlanStepRange::NextRangeBreakpointExplainsStop (lldb::StopInfoSP stop_info_sp) 340 { 341 if (!m_next_branch_bp_sp) 342 return false; 343 344 break_id_t bp_site_id = stop_info_sp->GetValue(); 345 BreakpointSiteSP bp_site_sp = m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id); 346 if (!bp_site_sp->IsBreakpointAtThisSite (m_next_branch_bp_sp->GetID())) 347 return false; 348 else 349 return bp_site_sp->GetNumberOfOwners() == 1; 350 } 351 352 bool 353 ThreadPlanStepRange::PlanExplainsStop () 354 { 355 // We always explain a stop. Either we've just done a single step, in which 356 // case we'll do our ordinary processing, or we stopped for some 357 // reason that isn't handled by our sub-plans, in which case we want to just stop right 358 // away. 359 360 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 361 StopInfoSP stop_info_sp = GetPrivateStopReason(); 362 if (stop_info_sp) 363 { 364 StopReason reason = stop_info_sp->GetStopReason(); 365 366 switch (reason) 367 { 368 case eStopReasonBreakpoint: 369 if (NextRangeBreakpointExplainsStop(stop_info_sp)) 370 return true; 371 case eStopReasonWatchpoint: 372 case eStopReasonSignal: 373 case eStopReasonException: 374 if (log) 375 log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step."); 376 SetPlanComplete(); 377 break; 378 default: 379 break; 380 } 381 } 382 return true; 383 } 384 385 bool 386 ThreadPlanStepRange::WillStop () 387 { 388 return true; 389 } 390 391 StateType 392 ThreadPlanStepRange::GetPlanRunState () 393 { 394 if (m_next_branch_bp_sp) 395 return eStateRunning; 396 else 397 return eStateStepping; 398 } 399 400 bool 401 ThreadPlanStepRange::MischiefManaged () 402 { 403 bool done = true; 404 if (!IsPlanComplete()) 405 { 406 if (InRange()) 407 { 408 done = false; 409 } 410 else 411 { 412 FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 413 if (frame_order != eFrameCompareOlder) 414 { 415 if (m_no_more_plans) 416 done = true; 417 else 418 done = false; 419 } 420 else 421 done = true; 422 } 423 } 424 425 if (done) 426 { 427 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 428 if (log) 429 log->Printf("Completed step through range plan."); 430 ThreadPlan::MischiefManaged (); 431 return true; 432 } 433 else 434 { 435 return false; 436 } 437 438 } 439