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 const char *plugin_name = NULL; 269 const char *flavor = NULL; 270 m_instruction_ranges[i] = Disassembler::DisassembleRange(GetTarget().GetArchitecture(), 271 plugin_name, 272 flavor, 273 exe_ctx, 274 m_address_ranges[i]); 275 276 } 277 if (!m_instruction_ranges[i]) 278 return NULL; 279 else 280 { 281 // Find where we are in the instruction list as well. If we aren't at an instruction, 282 // return NULL. In this case, we're probably lost, and shouldn't try to do anything fancy. 283 284 insn_offset = m_instruction_ranges[i]->GetInstructionList().GetIndexOfInstructionAtLoadAddress(addr, GetTarget()); 285 if (insn_offset == UINT32_MAX) 286 return NULL; 287 else 288 { 289 range_index = i; 290 return &m_instruction_ranges[i]->GetInstructionList(); 291 } 292 } 293 } 294 } 295 return NULL; 296 } 297 298 void 299 ThreadPlanStepRange::ClearNextBranchBreakpoint() 300 { 301 if (m_next_branch_bp_sp) 302 { 303 GetTarget().RemoveBreakpointByID (m_next_branch_bp_sp->GetID()); 304 m_next_branch_bp_sp.reset(); 305 } 306 } 307 308 bool 309 ThreadPlanStepRange::SetNextBranchBreakpoint () 310 { 311 // Stepping through ranges using breakpoints doesn't work yet, but with this off we fall back to instruction 312 // single stepping. 313 return false; 314 // Always clear the next branch breakpoint, we don't want to leave one of these stranded. 315 ClearNextBranchBreakpoint(); 316 lldb::addr_t cur_addr = GetThread().GetRegisterContext()->GetPC(); 317 // Find the current address in our address ranges, and fetch the disassembly if we haven't already: 318 size_t pc_index; 319 size_t range_index; 320 InstructionList *instructions = GetInstructionsForAddress (cur_addr, range_index, pc_index); 321 if (instructions == NULL) 322 return false; 323 else 324 { 325 uint32_t branch_index; 326 branch_index = instructions->GetIndexOfNextBranchInstruction (pc_index); 327 328 Address run_to_address; 329 330 // If we didn't find a branch, run to the end of the range. 331 if (branch_index == UINT32_MAX) 332 { 333 branch_index = instructions->GetSize() - 2; 334 } 335 if (branch_index - pc_index > 1) 336 { 337 const bool is_internal = true; 338 run_to_address = instructions->GetInstructionAtIndex(branch_index)->GetAddress(); 339 m_next_branch_bp_sp = GetTarget().CreateBreakpoint(run_to_address, is_internal); 340 if (m_next_branch_bp_sp) 341 { 342 m_next_branch_bp_sp->SetThreadID(m_thread.GetID()); 343 m_next_branch_bp_sp->SetBreakpointKind ("next-branch-location"); 344 } 345 else 346 return false; 347 } 348 } 349 return false; 350 } 351 352 bool 353 ThreadPlanStepRange::NextRangeBreakpointExplainsStop (lldb::StopInfoSP stop_info_sp) 354 { 355 if (!m_next_branch_bp_sp) 356 return false; 357 358 break_id_t bp_site_id = stop_info_sp->GetValue(); 359 BreakpointSiteSP bp_site_sp = m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id); 360 if (!bp_site_sp->IsBreakpointAtThisSite (m_next_branch_bp_sp->GetID())) 361 return false; 362 else 363 return bp_site_sp->GetNumberOfOwners() == 1; 364 } 365 366 bool 367 ThreadPlanStepRange::WillStop () 368 { 369 return true; 370 } 371 372 StateType 373 ThreadPlanStepRange::GetPlanRunState () 374 { 375 if (m_next_branch_bp_sp) 376 return eStateRunning; 377 else 378 return eStateStepping; 379 } 380 381 bool 382 ThreadPlanStepRange::MischiefManaged () 383 { 384 // If we have pushed some plans between ShouldStop & MischiefManaged, then we're not done... 385 // I do this check first because we might have stepped somewhere that will fool InRange into 386 // thinking it needs to step past the end of that line. This happens, for instance, when stepping 387 // over inlined code that is in the middle of the current line. 388 389 if (!m_no_more_plans) 390 return false; 391 392 bool done = true; 393 if (!IsPlanComplete()) 394 { 395 if (InRange()) 396 { 397 done = false; 398 } 399 else 400 { 401 FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 402 if (frame_order != eFrameCompareOlder) 403 { 404 if (m_no_more_plans) 405 done = true; 406 else 407 done = false; 408 } 409 else 410 done = true; 411 } 412 } 413 414 if (done) 415 { 416 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 417 if (log) 418 log->Printf("Completed step through range plan."); 419 ThreadPlan::MischiefManaged (); 420 return true; 421 } 422 else 423 { 424 return false; 425 } 426 427 } 428 429 bool 430 ThreadPlanStepRange::IsPlanStale () 431 { 432 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 433 FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 434 435 if (frame_order == eFrameCompareOlder) 436 { 437 if (log) 438 { 439 log->Printf("ThreadPlanStepRange::IsPlanStale returning true, we've stepped out."); 440 } 441 return true; 442 } 443 else if (frame_order == eFrameCompareEqual && InSymbol()) 444 { 445 // If we are not in a place we should step through, we've gotten stale. 446 // One tricky bit here is that some stubs don't push a frame, so we should. 447 // check that we are in the same symbol. 448 if (!InRange()) 449 { 450 return true; 451 } 452 } 453 return false; 454 } 455