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.Dump (&s, 150 m_thread.CalculateTarget().get(), 151 true, 152 Address::DumpStyleLoadAddress, 153 Address::DumpStyleLoadAddress, 154 true); 155 156 log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData()); 157 } 158 } 159 else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress(m_thread.CalculateTarget().get()) 160 != pc_load_addr) 161 { 162 // Another thing that sometimes happens here is that we step out of one line into the MIDDLE of another 163 // line. So far I mostly see this due to bugs in the debug information. 164 // But we probably don't want to be in the middle of a line range, so in that case reset the stepping 165 // range to the line we've stepped into the middle of and continue. 166 m_addr_context = new_context; 167 m_address_ranges.clear(); 168 AddRange(m_addr_context.line_entry.range); 169 ret_value = true; 170 if (log) 171 { 172 StreamString s; 173 m_addr_context.line_entry.Dump (&s, 174 m_thread.CalculateTarget().get(), 175 true, 176 Address::DumpStyleLoadAddress, 177 Address::DumpStyleLoadAddress, 178 true); 179 180 log->Printf ("Step range plan stepped to the middle of new line(%d): %s, continuing to clear this line.", 181 new_context.line_entry.line, 182 s.GetData()); 183 } 184 185 } 186 } 187 188 } 189 190 } 191 192 if (!ret_value && log) 193 log->Printf ("Step range plan out of range to 0x%" PRIx64, pc_load_addr); 194 195 return ret_value; 196 } 197 198 bool 199 ThreadPlanStepRange::InSymbol() 200 { 201 lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC(); 202 if (m_addr_context.function != NULL) 203 { 204 return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, m_thread.CalculateTarget().get()); 205 } 206 else if (m_addr_context.symbol) 207 { 208 AddressRange range(m_addr_context.symbol->GetAddress(), m_addr_context.symbol->GetByteSize()); 209 return range.ContainsLoadAddress (cur_pc, m_thread.CalculateTarget().get()); 210 } 211 return false; 212 } 213 214 // FIXME: This should also handle inlining if we aren't going to do inlining in the 215 // main stack. 216 // 217 // Ideally we should remember the whole stack frame list, and then compare that 218 // to the current list. 219 220 lldb::FrameComparison 221 ThreadPlanStepRange::CompareCurrentFrameToStartFrame() 222 { 223 FrameComparison frame_order; 224 225 StackID cur_frame_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 226 227 if (cur_frame_id == m_stack_id) 228 { 229 frame_order = eFrameCompareEqual; 230 } 231 else if (cur_frame_id < m_stack_id) 232 { 233 frame_order = eFrameCompareYounger; 234 } 235 else 236 { 237 frame_order = eFrameCompareOlder; 238 } 239 return frame_order; 240 } 241 242 bool 243 ThreadPlanStepRange::StopOthers () 244 { 245 if (m_stop_others == lldb::eOnlyThisThread 246 || m_stop_others == lldb::eOnlyDuringStepping) 247 return true; 248 else 249 return false; 250 } 251 252 InstructionList * 253 ThreadPlanStepRange::GetInstructionsForAddress(lldb::addr_t addr, size_t &range_index, size_t &insn_offset) 254 { 255 size_t num_ranges = m_address_ranges.size(); 256 for (size_t i = 0; i < num_ranges; i++) 257 { 258 if (m_address_ranges[i].ContainsLoadAddress(addr, &GetTarget())) 259 { 260 // Some joker added a zero size range to the stepping range... 261 if (m_address_ranges[i].GetByteSize() == 0) 262 return NULL; 263 264 if (!m_instruction_ranges[i]) 265 { 266 //Disassemble the address range given: 267 ExecutionContext exe_ctx (m_thread.GetProcess()); 268 m_instruction_ranges[i] = Disassembler::DisassembleRange(GetTarget().GetArchitecture(), 269 NULL, 270 exe_ctx, 271 m_address_ranges[i]); 272 273 } 274 if (!m_instruction_ranges[i]) 275 return NULL; 276 else 277 { 278 // Find where we are in the instruction list as well. If we aren't at an instruction, 279 // return NULL. In this case, we're probably lost, and shouldn't try to do anything fancy. 280 281 insn_offset = m_instruction_ranges[i]->GetInstructionList().GetIndexOfInstructionAtLoadAddress(addr, GetTarget()); 282 if (insn_offset == UINT32_MAX) 283 return NULL; 284 else 285 { 286 range_index = i; 287 return &m_instruction_ranges[i]->GetInstructionList(); 288 } 289 } 290 } 291 } 292 return NULL; 293 } 294 295 void 296 ThreadPlanStepRange::ClearNextBranchBreakpoint() 297 { 298 if (m_next_branch_bp_sp) 299 { 300 GetTarget().RemoveBreakpointByID (m_next_branch_bp_sp->GetID()); 301 m_next_branch_bp_sp.reset(); 302 } 303 } 304 305 bool 306 ThreadPlanStepRange::SetNextBranchBreakpoint () 307 { 308 // Stepping through ranges using breakpoints doesn't work yet, but with this off we fall back to instruction 309 // single stepping. 310 return false; 311 // Always clear the next branch breakpoint, we don't want to leave one of these stranded. 312 ClearNextBranchBreakpoint(); 313 lldb::addr_t cur_addr = GetThread().GetRegisterContext()->GetPC(); 314 // Find the current address in our address ranges, and fetch the disassembly if we haven't already: 315 size_t pc_index; 316 size_t range_index; 317 InstructionList *instructions = GetInstructionsForAddress (cur_addr, range_index, pc_index); 318 if (instructions == NULL) 319 return false; 320 else 321 { 322 uint32_t branch_index; 323 branch_index = instructions->GetIndexOfNextBranchInstruction (pc_index); 324 325 Address run_to_address; 326 327 // If we didn't find a branch, run to the end of the range. 328 if (branch_index == UINT32_MAX) 329 { 330 branch_index = instructions->GetSize() - 2; 331 } 332 if (branch_index - pc_index > 1) 333 { 334 const bool is_internal = true; 335 run_to_address = instructions->GetInstructionAtIndex(branch_index)->GetAddress(); 336 m_next_branch_bp_sp = GetTarget().CreateBreakpoint(run_to_address, is_internal); 337 if (m_next_branch_bp_sp) 338 { 339 m_next_branch_bp_sp->SetThreadID(m_thread.GetID()); 340 m_next_branch_bp_sp->SetBreakpointKind ("next-branch-location"); 341 } 342 else 343 return false; 344 } 345 } 346 return false; 347 } 348 349 bool 350 ThreadPlanStepRange::NextRangeBreakpointExplainsStop (lldb::StopInfoSP stop_info_sp) 351 { 352 if (!m_next_branch_bp_sp) 353 return false; 354 355 break_id_t bp_site_id = stop_info_sp->GetValue(); 356 BreakpointSiteSP bp_site_sp = m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id); 357 if (!bp_site_sp->IsBreakpointAtThisSite (m_next_branch_bp_sp->GetID())) 358 return false; 359 else 360 return bp_site_sp->GetNumberOfOwners() == 1; 361 } 362 363 bool 364 ThreadPlanStepRange::WillStop () 365 { 366 return true; 367 } 368 369 StateType 370 ThreadPlanStepRange::GetPlanRunState () 371 { 372 if (m_next_branch_bp_sp) 373 return eStateRunning; 374 else 375 return eStateStepping; 376 } 377 378 bool 379 ThreadPlanStepRange::MischiefManaged () 380 { 381 // If we have pushed some plans between ShouldStop & MischiefManaged, then we're not done... 382 // I do this check first because we might have stepped somewhere that will fool InRange into 383 // thinking it needs to step past the end of that line. This happens, for instance, when stepping 384 // over inlined code that is in the middle of the current line. 385 386 if (!m_no_more_plans) 387 return false; 388 389 bool done = true; 390 if (!IsPlanComplete()) 391 { 392 if (InRange()) 393 { 394 done = false; 395 } 396 else 397 { 398 FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 399 if (frame_order != eFrameCompareOlder) 400 { 401 if (m_no_more_plans) 402 done = true; 403 else 404 done = false; 405 } 406 else 407 done = true; 408 } 409 } 410 411 if (done) 412 { 413 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 414 if (log) 415 log->Printf("Completed step through range plan."); 416 ThreadPlan::MischiefManaged (); 417 return true; 418 } 419 else 420 { 421 return false; 422 } 423 424 } 425 426 bool 427 ThreadPlanStepRange::IsPlanStale () 428 { 429 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 430 FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 431 432 if (frame_order == eFrameCompareOlder) 433 { 434 if (log) 435 { 436 log->Printf("ThreadPlanStepRange::IsPlanStale returning true, we've stepped out."); 437 } 438 return true; 439 } 440 else if (frame_order == eFrameCompareEqual && InSymbol()) 441 { 442 // If we are not in a place we should step through, we've gotten stale. 443 // One tricky bit here is that some stubs don't push a frame, so we should. 444 // check that we are in the same symbol. 445 if (!InRange()) 446 { 447 return true; 448 } 449 } 450 return false; 451 } 452