1 //===-- SBThread.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/API/SBThread.h" 11 12 #include "lldb/API/SBSymbolContext.h" 13 #include "lldb/API/SBFileSpec.h" 14 #include "lldb/API/SBStream.h" 15 #include "lldb/Breakpoint/BreakpointLocation.h" 16 #include "lldb/Core/Debugger.h" 17 #include "lldb/Core/Stream.h" 18 #include "lldb/Core/StreamFile.h" 19 #include "lldb/Interpreter/CommandInterpreter.h" 20 #include "lldb/Target/Thread.h" 21 #include "lldb/Target/Process.h" 22 #include "lldb/Symbol/SymbolContext.h" 23 #include "lldb/Symbol/CompileUnit.h" 24 #include "lldb/Target/StopInfo.h" 25 #include "lldb/Target/Target.h" 26 #include "lldb/Target/ThreadPlan.h" 27 #include "lldb/Target/ThreadPlanStepInstruction.h" 28 #include "lldb/Target/ThreadPlanStepOut.h" 29 #include "lldb/Target/ThreadPlanStepRange.h" 30 #include "lldb/Target/ThreadPlanStepInRange.h" 31 32 33 #include "lldb/API/SBAddress.h" 34 #include "lldb/API/SBFrame.h" 35 #include "lldb/API/SBSourceManager.h" 36 #include "lldb/API/SBDebugger.h" 37 #include "lldb/API/SBProcess.h" 38 39 using namespace lldb; 40 using namespace lldb_private; 41 42 //---------------------------------------------------------------------- 43 // Constructors 44 //---------------------------------------------------------------------- 45 SBThread::SBThread () : 46 m_opaque_sp () 47 { 48 } 49 50 SBThread::SBThread (const ThreadSP& lldb_object_sp) : 51 m_opaque_sp (lldb_object_sp) 52 { 53 } 54 55 SBThread::SBThread (const SBThread &rhs) : 56 m_opaque_sp (rhs.m_opaque_sp) 57 { 58 } 59 60 //---------------------------------------------------------------------- 61 // Assignment operator 62 //---------------------------------------------------------------------- 63 64 const lldb::SBThread & 65 SBThread::operator = (const SBThread &rhs) 66 { 67 if (this != &rhs) 68 m_opaque_sp = rhs.m_opaque_sp; 69 return *this; 70 } 71 72 //---------------------------------------------------------------------- 73 // Destructor 74 //---------------------------------------------------------------------- 75 SBThread::~SBThread() 76 { 77 } 78 79 bool 80 SBThread::IsValid() const 81 { 82 return m_opaque_sp != NULL; 83 } 84 85 void 86 SBThread::Clear () 87 { 88 m_opaque_sp.reset(); 89 } 90 91 92 StopReason 93 SBThread::GetStopReason() 94 { 95 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 96 97 StopReason reason = eStopReasonInvalid; 98 if (m_opaque_sp) 99 { 100 Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex()); 101 StopInfoSP stop_info_sp = m_opaque_sp->GetStopInfo (); 102 if (stop_info_sp) 103 reason = stop_info_sp->GetStopReason(); 104 } 105 106 if (log) 107 log->Printf ("SBThread(%p)::GetStopReason () => %s", m_opaque_sp.get(), 108 Thread::StopReasonAsCString (reason)); 109 110 return reason; 111 } 112 113 size_t 114 SBThread::GetStopReasonDataCount () 115 { 116 if (m_opaque_sp) 117 { 118 Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex()); 119 StopInfoSP stop_info_sp = m_opaque_sp->GetStopInfo (); 120 if (stop_info_sp) 121 { 122 StopReason reason = stop_info_sp->GetStopReason(); 123 switch (reason) 124 { 125 case eStopReasonInvalid: 126 case eStopReasonNone: 127 case eStopReasonTrace: 128 case eStopReasonPlanComplete: 129 // There is no data for these stop reasons. 130 return 0; 131 132 case eStopReasonBreakpoint: 133 { 134 break_id_t site_id = stop_info_sp->GetValue(); 135 lldb::BreakpointSiteSP bp_site_sp (m_opaque_sp->GetProcess().GetBreakpointSiteList().FindByID (site_id)); 136 if (bp_site_sp) 137 return bp_site_sp->GetNumberOfOwners () * 2; 138 else 139 return 0; // Breakpoint must have cleared itself... 140 } 141 break; 142 143 case eStopReasonWatchpoint: 144 assert (!"implement watchpoint support in SBThread::GetStopReasonDataCount ()"); 145 return 0; // We don't have watchpoint support yet... 146 147 case eStopReasonSignal: 148 return 1; 149 150 case eStopReasonException: 151 return 1; 152 } 153 } 154 } 155 return 0; 156 } 157 158 uint64_t 159 SBThread::GetStopReasonDataAtIndex (uint32_t idx) 160 { 161 if (m_opaque_sp) 162 { 163 Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex()); 164 StopInfoSP stop_info_sp = m_opaque_sp->GetStopInfo (); 165 if (stop_info_sp) 166 { 167 StopReason reason = stop_info_sp->GetStopReason(); 168 switch (reason) 169 { 170 case eStopReasonInvalid: 171 case eStopReasonNone: 172 case eStopReasonTrace: 173 case eStopReasonPlanComplete: 174 // There is no data for these stop reasons. 175 return 0; 176 177 case eStopReasonBreakpoint: 178 { 179 break_id_t site_id = stop_info_sp->GetValue(); 180 lldb::BreakpointSiteSP bp_site_sp (m_opaque_sp->GetProcess().GetBreakpointSiteList().FindByID (site_id)); 181 if (bp_site_sp) 182 { 183 uint32_t bp_index = idx / 2; 184 BreakpointLocationSP bp_loc_sp (bp_site_sp->GetOwnerAtIndex (bp_index)); 185 if (bp_loc_sp) 186 { 187 if (bp_index & 1) 188 { 189 // Odd idx, return the breakpoint location ID 190 return bp_loc_sp->GetID(); 191 } 192 else 193 { 194 // Even idx, return the breakpoint ID 195 return bp_loc_sp->GetBreakpoint().GetID(); 196 } 197 } 198 } 199 return LLDB_INVALID_BREAK_ID; 200 } 201 break; 202 203 case eStopReasonWatchpoint: 204 assert (!"implement watchpoint support in SBThread::GetStopReasonDataCount ()"); 205 return 0; // We don't have watchpoint support yet... 206 207 case eStopReasonSignal: 208 return stop_info_sp->GetValue(); 209 210 case eStopReasonException: 211 return stop_info_sp->GetValue(); 212 } 213 } 214 } 215 return 0; 216 } 217 218 size_t 219 SBThread::GetStopDescription (char *dst, size_t dst_len) 220 { 221 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 222 223 if (m_opaque_sp) 224 { 225 Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex()); 226 StopInfoSP stop_info_sp = m_opaque_sp->GetStopInfo (); 227 if (stop_info_sp) 228 { 229 const char *stop_desc = stop_info_sp->GetDescription(); 230 if (stop_desc) 231 { 232 if (log) 233 log->Printf ("SBThread(%p)::GetStopDescription (dst, dst_len) => \"%s\"", 234 m_opaque_sp.get(), stop_desc); 235 if (dst) 236 return ::snprintf (dst, dst_len, "%s", stop_desc); 237 else 238 { 239 // NULL dst passed in, return the length needed to contain the description 240 return ::strlen (stop_desc) + 1; // Include the NULL byte for size 241 } 242 } 243 else 244 { 245 size_t stop_desc_len = 0; 246 switch (stop_info_sp->GetStopReason()) 247 { 248 case eStopReasonTrace: 249 case eStopReasonPlanComplete: 250 { 251 static char trace_desc[] = "step"; 252 stop_desc = trace_desc; 253 stop_desc_len = sizeof(trace_desc); // Include the NULL byte for size 254 } 255 break; 256 257 case eStopReasonBreakpoint: 258 { 259 static char bp_desc[] = "breakpoint hit"; 260 stop_desc = bp_desc; 261 stop_desc_len = sizeof(bp_desc); // Include the NULL byte for size 262 } 263 break; 264 265 case eStopReasonWatchpoint: 266 { 267 static char wp_desc[] = "watchpoint hit"; 268 stop_desc = wp_desc; 269 stop_desc_len = sizeof(wp_desc); // Include the NULL byte for size 270 } 271 break; 272 273 case eStopReasonSignal: 274 { 275 stop_desc = m_opaque_sp->GetProcess().GetUnixSignals ().GetSignalAsCString (stop_info_sp->GetValue()); 276 if (stop_desc == NULL || stop_desc[0] == '\0') 277 { 278 static char signal_desc[] = "signal"; 279 stop_desc = signal_desc; 280 stop_desc_len = sizeof(signal_desc); // Include the NULL byte for size 281 } 282 } 283 break; 284 285 case eStopReasonException: 286 { 287 char exc_desc[] = "exception"; 288 stop_desc = exc_desc; 289 stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size 290 } 291 break; 292 293 default: 294 break; 295 } 296 297 if (stop_desc && stop_desc[0]) 298 { 299 if (log) 300 log->Printf ("SBThread(%p)::GetStopDescription (dst, dst_len) => '%s'", 301 m_opaque_sp.get(), stop_desc); 302 303 if (dst) 304 return ::snprintf (dst, dst_len, "%s", stop_desc) + 1; // Include the NULL byte 305 306 if (stop_desc_len == 0) 307 stop_desc_len = ::strlen (stop_desc) + 1; // Include the NULL byte 308 309 return stop_desc_len; 310 } 311 } 312 } 313 } 314 if (dst) 315 *dst = 0; 316 return 0; 317 } 318 319 void 320 SBThread::SetThread (const ThreadSP& lldb_object_sp) 321 { 322 m_opaque_sp = lldb_object_sp; 323 } 324 325 326 lldb::tid_t 327 SBThread::GetThreadID () const 328 { 329 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 330 331 lldb::tid_t tid = LLDB_INVALID_THREAD_ID; 332 if (m_opaque_sp) 333 tid = m_opaque_sp->GetID(); 334 335 if (log) 336 log->Printf ("SBThread(%p)::GetThreadID () => 0x%4.4x", m_opaque_sp.get(), tid); 337 338 return tid; 339 } 340 341 uint32_t 342 SBThread::GetIndexID () const 343 { 344 if (m_opaque_sp) 345 return m_opaque_sp->GetIndexID(); 346 return LLDB_INVALID_INDEX32; 347 } 348 const char * 349 SBThread::GetName () const 350 { 351 const char *name = NULL; 352 if (m_opaque_sp) 353 { 354 Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex()); 355 name = m_opaque_sp->GetName(); 356 } 357 358 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 359 if (log) 360 log->Printf ("SBThread(%p)::GetName () => %s", m_opaque_sp.get(), name ? name : "NULL"); 361 362 return name; 363 } 364 365 const char * 366 SBThread::GetQueueName () const 367 { 368 const char *name = NULL; 369 if (m_opaque_sp) 370 { 371 Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex()); 372 name = m_opaque_sp->GetQueueName(); 373 } 374 375 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 376 if (log) 377 log->Printf ("SBThread(%p)::GetQueueName () => %s", m_opaque_sp.get(), name ? name : "NULL"); 378 379 return name; 380 } 381 382 383 void 384 SBThread::StepOver (lldb::RunMode stop_other_threads) 385 { 386 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 387 388 if (log) 389 log->Printf ("SBThread(%p)::StepOver (stop_other_threads='%s')", m_opaque_sp.get(), 390 Thread::RunModeAsCString (stop_other_threads)); 391 392 if (m_opaque_sp) 393 { 394 Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex()); 395 bool abort_other_plans = true; 396 StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0)); 397 398 if (frame_sp) 399 { 400 if (frame_sp->HasDebugInformation ()) 401 { 402 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); 403 m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans, 404 eStepTypeOver, 405 sc.line_entry.range, 406 sc, 407 stop_other_threads, 408 false); 409 410 } 411 else 412 { 413 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (true, 414 abort_other_plans, 415 stop_other_threads); 416 } 417 } 418 419 Process &process = m_opaque_sp->GetProcess(); 420 // Why do we need to set the current thread by ID here??? 421 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 422 Error error (process.Resume()); 423 if (error.Success()) 424 { 425 // If we are doing synchronous mode, then wait for the 426 // process to stop yet again! 427 if (process.GetTarget().GetDebugger().GetAsyncExecution () == false) 428 process.WaitForProcessToStop (NULL); 429 } 430 } 431 } 432 433 void 434 SBThread::StepInto (lldb::RunMode stop_other_threads) 435 { 436 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 437 438 if (log) 439 log->Printf ("SBThread(%p)::StepInto (stop_other_threads='%s')", m_opaque_sp.get(), 440 Thread::RunModeAsCString (stop_other_threads)); 441 442 if (m_opaque_sp) 443 { 444 Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex()); 445 bool abort_other_plans = true; 446 447 StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0)); 448 449 if (frame_sp && frame_sp->HasDebugInformation ()) 450 { 451 bool avoid_code_without_debug_info = true; 452 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); 453 m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans, 454 eStepTypeInto, 455 sc.line_entry.range, 456 sc, 457 stop_other_threads, 458 avoid_code_without_debug_info); 459 } 460 else 461 { 462 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (false, 463 abort_other_plans, 464 stop_other_threads); 465 } 466 467 Process &process = m_opaque_sp->GetProcess(); 468 // Why do we need to set the current thread by ID here??? 469 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 470 Error error (process.Resume()); 471 if (error.Success()) 472 { 473 // If we are doing synchronous mode, then wait for the 474 // process to stop yet again! 475 if (process.GetTarget().GetDebugger().GetAsyncExecution () == false) 476 process.WaitForProcessToStop (NULL); 477 } 478 } 479 } 480 481 void 482 SBThread::StepOut () 483 { 484 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 485 486 if (log) 487 log->Printf ("SBThread(%p)::StepOut ()", m_opaque_sp.get()); 488 489 if (m_opaque_sp) 490 { 491 Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex()); 492 bool abort_other_plans = true; 493 bool stop_other_threads = true; 494 495 m_opaque_sp->QueueThreadPlanForStepOut (abort_other_plans, 496 NULL, 497 false, 498 stop_other_threads, 499 eVoteYes, 500 eVoteNoOpinion, 501 0); 502 503 Process &process = m_opaque_sp->GetProcess(); 504 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 505 Error error (process.Resume()); 506 if (error.Success()) 507 { 508 // If we are doing synchronous mode, then wait for the 509 // process to stop yet again! 510 if (process.GetTarget().GetDebugger().GetAsyncExecution () == false) 511 process.WaitForProcessToStop (NULL); 512 } 513 } 514 } 515 516 void 517 SBThread::StepOutOfFrame (lldb::SBFrame &sb_frame) 518 { 519 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 520 521 if (log) 522 { 523 SBStream frame_desc_strm; 524 sb_frame.GetDescription (frame_desc_strm); 525 log->Printf ("SBThread(%p)::StepOutOfFrame (frame = SBFrame(%p): %s)", m_opaque_sp.get(), sb_frame.get(), frame_desc_strm.GetData()); 526 } 527 528 if (m_opaque_sp) 529 { 530 Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex()); 531 bool abort_other_plans = true; 532 bool stop_other_threads = true; 533 534 m_opaque_sp->QueueThreadPlanForStepOut (abort_other_plans, 535 NULL, 536 false, 537 stop_other_threads, 538 eVoteYes, 539 eVoteNoOpinion, 540 sb_frame->GetFrameIndex()); 541 542 Process &process = m_opaque_sp->GetProcess(); 543 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 544 Error error (process.Resume()); 545 if (error.Success()) 546 { 547 // If we are doing synchronous mode, then wait for the 548 // process to stop yet again! 549 if (process.GetTarget().GetDebugger().GetAsyncExecution () == false) 550 process.WaitForProcessToStop (NULL); 551 } 552 } 553 } 554 555 void 556 SBThread::StepInstruction (bool step_over) 557 { 558 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 559 560 if (log) 561 log->Printf ("SBThread(%p)::StepInstruction (step_over=%i)", m_opaque_sp.get(), step_over); 562 563 if (m_opaque_sp) 564 { 565 Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex()); 566 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (step_over, true, true); 567 Process &process = m_opaque_sp->GetProcess(); 568 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 569 Error error (process.Resume()); 570 if (error.Success()) 571 { 572 // If we are doing synchronous mode, then wait for the 573 // process to stop yet again! 574 if (process.GetTarget().GetDebugger().GetAsyncExecution () == false) 575 process.WaitForProcessToStop (NULL); 576 } 577 } 578 } 579 580 void 581 SBThread::RunToAddress (lldb::addr_t addr) 582 { 583 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 584 585 if (log) 586 log->Printf ("SBThread(%p)::RunToAddress (addr=0x%llx)", m_opaque_sp.get(), addr); 587 588 if (m_opaque_sp) 589 { 590 bool abort_other_plans = true; 591 bool stop_other_threads = true; 592 593 Address target_addr (NULL, addr); 594 595 m_opaque_sp->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads); 596 Process &process = m_opaque_sp->GetProcess(); 597 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 598 Error error (process.Resume()); 599 if (error.Success()) 600 { 601 // If we are doing synchronous mode, then wait for the 602 // process to stop yet again! 603 if (process.GetTarget().GetDebugger().GetAsyncExecution () == false) 604 process.WaitForProcessToStop (NULL); 605 } 606 } 607 } 608 609 SBError 610 SBThread::StepOverUntil (lldb::SBFrame &sb_frame, 611 lldb::SBFileSpec &sb_file_spec, 612 uint32_t line) 613 { 614 SBError sb_error; 615 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 616 char path[PATH_MAX]; 617 618 if (log) 619 { 620 SBStream frame_desc_strm; 621 sb_frame.GetDescription (frame_desc_strm); 622 sb_file_spec->GetPath (path, sizeof(path)); 623 log->Printf ("SBThread(%p)::StepOverUntil (frame = SBFrame(%p): %s, file+line = %s:%u)", 624 m_opaque_sp.get(), 625 sb_frame.get(), 626 frame_desc_strm.GetData(), 627 path, line); 628 } 629 630 if (m_opaque_sp) 631 { 632 Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex()); 633 634 if (line == 0) 635 { 636 sb_error.SetErrorString("invalid line argument"); 637 return sb_error; 638 } 639 640 StackFrameSP frame_sp; 641 if (sb_frame.IsValid()) 642 frame_sp = sb_frame.get_sp(); 643 else 644 { 645 frame_sp = m_opaque_sp->GetSelectedFrame (); 646 if (!frame_sp) 647 frame_sp = m_opaque_sp->GetStackFrameAtIndex (0); 648 } 649 650 SymbolContext frame_sc; 651 if (!frame_sp) 652 { 653 sb_error.SetErrorString("no valid frames in thread to step"); 654 return sb_error; 655 } 656 657 // If we have a frame, get its line 658 frame_sc = frame_sp->GetSymbolContext (eSymbolContextCompUnit | 659 eSymbolContextFunction | 660 eSymbolContextLineEntry | 661 eSymbolContextSymbol ); 662 663 if (frame_sc.comp_unit == NULL) 664 { 665 sb_error.SetErrorStringWithFormat("frame %u doesn't have debug information", frame_sp->GetFrameIndex()); 666 return sb_error; 667 } 668 669 FileSpec step_file_spec; 670 if (sb_file_spec.IsValid()) 671 { 672 // The file spec passed in was valid, so use it 673 step_file_spec = sb_file_spec.ref(); 674 } 675 else 676 { 677 if (frame_sc.line_entry.IsValid()) 678 step_file_spec = frame_sc.line_entry.file; 679 else 680 { 681 sb_error.SetErrorString("invalid file argument or no file for frame"); 682 return sb_error; 683 } 684 } 685 686 std::vector<addr_t> step_over_until_addrs; 687 const bool abort_other_plans = true; 688 const bool stop_other_threads = true; 689 const bool check_inlines = true; 690 const bool exact = false; 691 692 SymbolContextList sc_list; 693 const uint32_t num_matches = frame_sc.comp_unit->ResolveSymbolContext (step_file_spec, line, check_inlines, exact, eSymbolContextLineEntry, sc_list); 694 if (num_matches > 0) 695 { 696 SymbolContext sc; 697 for (uint32_t i=0; i<num_matches; ++i) 698 { 699 if (sc_list.GetContextAtIndex(i, sc)) 700 { 701 addr_t step_addr = sc.line_entry.range.GetBaseAddress().GetLoadAddress(&m_opaque_sp->GetProcess().GetTarget()); 702 if (step_addr != LLDB_INVALID_ADDRESS) 703 { 704 step_over_until_addrs.push_back(step_addr); 705 } 706 } 707 } 708 } 709 710 if (step_over_until_addrs.empty()) 711 { 712 step_file_spec.GetPath (path, sizeof(path)); 713 sb_error.SetErrorStringWithFormat("No line entries for %s:u", path, line); 714 } 715 else 716 { 717 m_opaque_sp->QueueThreadPlanForStepUntil (abort_other_plans, 718 &step_over_until_addrs[0], 719 step_over_until_addrs.size(), 720 stop_other_threads, 721 frame_sp->GetFrameIndex()); 722 723 m_opaque_sp->GetProcess().GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 724 sb_error.ref() = m_opaque_sp->GetProcess().Resume(); 725 if (sb_error->Success()) 726 { 727 // If we are doing synchronous mode, then wait for the 728 // process to stop yet again! 729 if (m_opaque_sp->GetProcess().GetTarget().GetDebugger().GetAsyncExecution () == false) 730 m_opaque_sp->GetProcess().WaitForProcessToStop (NULL); 731 } 732 } 733 } 734 else 735 { 736 sb_error.SetErrorString("this SBThread object is invalid"); 737 } 738 return sb_error; 739 } 740 741 742 bool 743 SBThread::Suspend() 744 { 745 if (m_opaque_sp) 746 { 747 m_opaque_sp->SetResumeState (eStateSuspended); 748 return true; 749 } 750 return false; 751 } 752 753 bool 754 SBThread::Resume () 755 { 756 if (m_opaque_sp) 757 { 758 m_opaque_sp->SetResumeState (eStateRunning); 759 return true; 760 } 761 return false; 762 } 763 764 bool 765 SBThread::IsSuspended() 766 { 767 if (m_opaque_sp) 768 return m_opaque_sp->GetResumeState () == eStateSuspended; 769 return false; 770 } 771 772 SBProcess 773 SBThread::GetProcess () 774 { 775 776 SBProcess process; 777 if (m_opaque_sp) 778 { 779 // Have to go up to the target so we can get a shared pointer to our process... 780 process.SetProcess(m_opaque_sp->GetProcess().GetTarget().GetProcessSP()); 781 } 782 783 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 784 if (log) 785 { 786 SBStream frame_desc_strm; 787 process.GetDescription (frame_desc_strm); 788 log->Printf ("SBThread(%p)::GetProcess () => SBProcess(%p): %s", m_opaque_sp.get(), 789 process.get(), frame_desc_strm.GetData()); 790 } 791 792 return process; 793 } 794 795 uint32_t 796 SBThread::GetNumFrames () 797 { 798 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 799 800 uint32_t num_frames = 0; 801 if (m_opaque_sp) 802 { 803 Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex()); 804 num_frames = m_opaque_sp->GetStackFrameCount(); 805 } 806 807 if (log) 808 log->Printf ("SBThread(%p)::GetNumFrames () => %u", m_opaque_sp.get(), num_frames); 809 810 return num_frames; 811 } 812 813 SBFrame 814 SBThread::GetFrameAtIndex (uint32_t idx) 815 { 816 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 817 818 SBFrame sb_frame; 819 if (m_opaque_sp) 820 { 821 Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex()); 822 sb_frame.SetFrame (m_opaque_sp->GetStackFrameAtIndex (idx)); 823 } 824 825 if (log) 826 { 827 SBStream frame_desc_strm; 828 sb_frame.GetDescription (frame_desc_strm); 829 log->Printf ("SBThread(%p)::GetFrameAtIndex (idx=%d) => SBFrame(%p): %s", 830 m_opaque_sp.get(), idx, sb_frame.get(), frame_desc_strm.GetData()); 831 } 832 833 return sb_frame; 834 } 835 836 lldb::SBFrame 837 SBThread::GetSelectedFrame () 838 { 839 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 840 841 SBFrame sb_frame; 842 if (m_opaque_sp) 843 { 844 Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex()); 845 sb_frame.SetFrame (m_opaque_sp->GetSelectedFrame ()); 846 } 847 848 if (log) 849 { 850 SBStream frame_desc_strm; 851 sb_frame.GetDescription (frame_desc_strm); 852 log->Printf ("SBThread(%p)::GetSelectedFrame () => SBFrame(%p): %s", 853 m_opaque_sp.get(), sb_frame.get(), frame_desc_strm.GetData()); 854 } 855 856 return sb_frame; 857 } 858 859 lldb::SBFrame 860 SBThread::SetSelectedFrame (uint32_t idx) 861 { 862 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 863 864 SBFrame sb_frame; 865 if (m_opaque_sp) 866 { 867 Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex()); 868 lldb::StackFrameSP frame_sp (m_opaque_sp->GetStackFrameAtIndex (idx)); 869 if (frame_sp) 870 { 871 m_opaque_sp->SetSelectedFrame (frame_sp.get()); 872 sb_frame.SetFrame (frame_sp); 873 } 874 } 875 876 if (log) 877 { 878 SBStream frame_desc_strm; 879 sb_frame.GetDescription (frame_desc_strm); 880 log->Printf ("SBThread(%p)::SetSelectedFrame (idx=%u) => SBFrame(%p): %s", 881 m_opaque_sp.get(), idx, sb_frame.get(), frame_desc_strm.GetData()); 882 } 883 return sb_frame; 884 } 885 886 887 bool 888 SBThread::operator == (const SBThread &rhs) const 889 { 890 return m_opaque_sp.get() == rhs.m_opaque_sp.get(); 891 } 892 893 bool 894 SBThread::operator != (const SBThread &rhs) const 895 { 896 return m_opaque_sp.get() != rhs.m_opaque_sp.get(); 897 } 898 899 lldb_private::Thread * 900 SBThread::get () 901 { 902 return m_opaque_sp.get(); 903 } 904 905 const lldb_private::Thread * 906 SBThread::operator->() const 907 { 908 return m_opaque_sp.get(); 909 } 910 911 const lldb_private::Thread & 912 SBThread::operator*() const 913 { 914 return *m_opaque_sp; 915 } 916 917 lldb_private::Thread * 918 SBThread::operator->() 919 { 920 return m_opaque_sp.get(); 921 } 922 923 lldb_private::Thread & 924 SBThread::operator*() 925 { 926 return *m_opaque_sp; 927 } 928 929 bool 930 SBThread::GetDescription (SBStream &description) const 931 { 932 if (m_opaque_sp) 933 { 934 StreamString strm; 935 description.Printf("SBThread: tid = 0x%4.4x", m_opaque_sp->GetID()); 936 } 937 else 938 description.Printf ("No value"); 939 940 return true; 941 } 942