SBThread.cpp revision 6b70f0317707698df7c26bdfebbe90b41087e0ab
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/SBDebugger.h" 35#include "lldb/API/SBFrame.h" 36#include "lldb/API/SBProcess.h" 37#include "lldb/API/SBValue.h" 38 39using namespace lldb; 40using namespace lldb_private; 41 42//---------------------------------------------------------------------- 43// Constructors 44//---------------------------------------------------------------------- 45SBThread::SBThread () : 46 m_opaque_sp (new ExecutionContextRef()) 47{ 48} 49 50SBThread::SBThread (const ThreadSP& lldb_object_sp) : 51 m_opaque_sp (new ExecutionContextRef(lldb_object_sp)) 52{ 53} 54 55SBThread::SBThread (const SBThread &rhs) : 56 m_opaque_sp (new ExecutionContextRef(*rhs.m_opaque_sp)) 57{ 58 59} 60 61//---------------------------------------------------------------------- 62// Assignment operator 63//---------------------------------------------------------------------- 64 65const lldb::SBThread & 66SBThread::operator = (const SBThread &rhs) 67{ 68 if (this != &rhs) 69 *m_opaque_sp = *rhs.m_opaque_sp; 70 return *this; 71} 72 73//---------------------------------------------------------------------- 74// Destructor 75//---------------------------------------------------------------------- 76SBThread::~SBThread() 77{ 78} 79 80bool 81SBThread::IsValid() const 82{ 83 return m_opaque_sp->GetThreadSP().get() != NULL; 84} 85 86void 87SBThread::Clear () 88{ 89 m_opaque_sp->Clear(); 90} 91 92 93StopReason 94SBThread::GetStopReason() 95{ 96 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 97 98 StopReason reason = eStopReasonInvalid; 99 Mutex::Locker api_locker; 100 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 101 102 if (exe_ctx.HasThreadScope()) 103 { 104 Process::StopLocker stop_locker; 105 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 106 { 107 StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo (); 108 if (stop_info_sp) 109 reason = stop_info_sp->GetStopReason(); 110 } 111 else 112 { 113 if (log) 114 log->Printf ("SBThread(%p)::GetStopReason() => error: process is running", exe_ctx.GetThreadPtr()); 115 } 116 } 117 118 if (log) 119 log->Printf ("SBThread(%p)::GetStopReason () => %s", exe_ctx.GetThreadPtr(), 120 Thread::StopReasonAsCString (reason)); 121 122 return reason; 123} 124 125size_t 126SBThread::GetStopReasonDataCount () 127{ 128 Mutex::Locker api_locker; 129 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 130 131 if (exe_ctx.HasThreadScope()) 132 { 133 Process::StopLocker stop_locker; 134 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 135 { 136 StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo (); 137 if (stop_info_sp) 138 { 139 StopReason reason = stop_info_sp->GetStopReason(); 140 switch (reason) 141 { 142 case eStopReasonInvalid: 143 case eStopReasonNone: 144 case eStopReasonTrace: 145 case eStopReasonPlanComplete: 146 // There is no data for these stop reasons. 147 return 0; 148 149 case eStopReasonBreakpoint: 150 { 151 break_id_t site_id = stop_info_sp->GetValue(); 152 lldb::BreakpointSiteSP bp_site_sp (exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID (site_id)); 153 if (bp_site_sp) 154 return bp_site_sp->GetNumberOfOwners () * 2; 155 else 156 return 0; // Breakpoint must have cleared itself... 157 } 158 break; 159 160 case eStopReasonWatchpoint: 161 return 1; 162 163 case eStopReasonSignal: 164 return 1; 165 166 case eStopReasonException: 167 return 1; 168 } 169 } 170 } 171 else 172 { 173 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 174 if (log) 175 log->Printf ("SBThread(%p)::GetStopReasonDataCount() => error: process is running", exe_ctx.GetThreadPtr()); 176 } 177 } 178 return 0; 179} 180 181uint64_t 182SBThread::GetStopReasonDataAtIndex (uint32_t idx) 183{ 184 Mutex::Locker api_locker; 185 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 186 187 if (exe_ctx.HasThreadScope()) 188 { 189 Process::StopLocker stop_locker; 190 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 191 { 192 Thread *thread = exe_ctx.GetThreadPtr(); 193 StopInfoSP stop_info_sp = thread->GetStopInfo (); 194 if (stop_info_sp) 195 { 196 StopReason reason = stop_info_sp->GetStopReason(); 197 switch (reason) 198 { 199 case eStopReasonInvalid: 200 case eStopReasonNone: 201 case eStopReasonTrace: 202 case eStopReasonPlanComplete: 203 // There is no data for these stop reasons. 204 return 0; 205 206 case eStopReasonBreakpoint: 207 { 208 break_id_t site_id = stop_info_sp->GetValue(); 209 lldb::BreakpointSiteSP bp_site_sp (exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID (site_id)); 210 if (bp_site_sp) 211 { 212 uint32_t bp_index = idx / 2; 213 BreakpointLocationSP bp_loc_sp (bp_site_sp->GetOwnerAtIndex (bp_index)); 214 if (bp_loc_sp) 215 { 216 if (bp_index & 1) 217 { 218 // Odd idx, return the breakpoint location ID 219 return bp_loc_sp->GetID(); 220 } 221 else 222 { 223 // Even idx, return the breakpoint ID 224 return bp_loc_sp->GetBreakpoint().GetID(); 225 } 226 } 227 } 228 return LLDB_INVALID_BREAK_ID; 229 } 230 break; 231 232 case eStopReasonWatchpoint: 233 return stop_info_sp->GetValue(); 234 235 case eStopReasonSignal: 236 return stop_info_sp->GetValue(); 237 238 case eStopReasonException: 239 return stop_info_sp->GetValue(); 240 } 241 } 242 } 243 else 244 { 245 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 246 if (log) 247 log->Printf ("SBThread(%p)::GetStopReasonDataAtIndex() => error: process is running", exe_ctx.GetThreadPtr()); 248 } 249 } 250 return 0; 251} 252 253size_t 254SBThread::GetStopDescription (char *dst, size_t dst_len) 255{ 256 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 257 258 Mutex::Locker api_locker; 259 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 260 261 if (exe_ctx.HasThreadScope()) 262 { 263 Process::StopLocker stop_locker; 264 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 265 { 266 267 StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo (); 268 if (stop_info_sp) 269 { 270 const char *stop_desc = stop_info_sp->GetDescription(); 271 if (stop_desc) 272 { 273 if (log) 274 log->Printf ("SBThread(%p)::GetStopDescription (dst, dst_len) => \"%s\"", 275 exe_ctx.GetThreadPtr(), stop_desc); 276 if (dst) 277 return ::snprintf (dst, dst_len, "%s", stop_desc); 278 else 279 { 280 // NULL dst passed in, return the length needed to contain the description 281 return ::strlen (stop_desc) + 1; // Include the NULL byte for size 282 } 283 } 284 else 285 { 286 size_t stop_desc_len = 0; 287 switch (stop_info_sp->GetStopReason()) 288 { 289 case eStopReasonTrace: 290 case eStopReasonPlanComplete: 291 { 292 static char trace_desc[] = "step"; 293 stop_desc = trace_desc; 294 stop_desc_len = sizeof(trace_desc); // Include the NULL byte for size 295 } 296 break; 297 298 case eStopReasonBreakpoint: 299 { 300 static char bp_desc[] = "breakpoint hit"; 301 stop_desc = bp_desc; 302 stop_desc_len = sizeof(bp_desc); // Include the NULL byte for size 303 } 304 break; 305 306 case eStopReasonWatchpoint: 307 { 308 static char wp_desc[] = "watchpoint hit"; 309 stop_desc = wp_desc; 310 stop_desc_len = sizeof(wp_desc); // Include the NULL byte for size 311 } 312 break; 313 314 case eStopReasonSignal: 315 { 316 stop_desc = exe_ctx.GetProcessPtr()->GetUnixSignals ().GetSignalAsCString (stop_info_sp->GetValue()); 317 if (stop_desc == NULL || stop_desc[0] == '\0') 318 { 319 static char signal_desc[] = "signal"; 320 stop_desc = signal_desc; 321 stop_desc_len = sizeof(signal_desc); // Include the NULL byte for size 322 } 323 } 324 break; 325 326 case eStopReasonException: 327 { 328 char exc_desc[] = "exception"; 329 stop_desc = exc_desc; 330 stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size 331 } 332 break; 333 334 default: 335 break; 336 } 337 338 if (stop_desc && stop_desc[0]) 339 { 340 if (log) 341 log->Printf ("SBThread(%p)::GetStopDescription (dst, dst_len) => '%s'", 342 exe_ctx.GetThreadPtr(), stop_desc); 343 344 if (dst) 345 return ::snprintf (dst, dst_len, "%s", stop_desc) + 1; // Include the NULL byte 346 347 if (stop_desc_len == 0) 348 stop_desc_len = ::strlen (stop_desc) + 1; // Include the NULL byte 349 350 return stop_desc_len; 351 } 352 } 353 } 354 } 355 else 356 { 357 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 358 if (log) 359 log->Printf ("SBThread(%p)::GetStopDescription() => error: process is running", exe_ctx.GetThreadPtr()); 360 } 361 } 362 if (dst) 363 *dst = 0; 364 return 0; 365} 366 367SBValue 368SBThread::GetStopReturnValue () 369{ 370 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 371 ValueObjectSP return_valobj_sp; 372 Mutex::Locker api_locker; 373 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 374 375 if (exe_ctx.HasThreadScope()) 376 { 377 Process::StopLocker stop_locker; 378 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 379 { 380 StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo (); 381 if (stop_info_sp) 382 { 383 return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp); 384 } 385 } 386 else 387 { 388 if (log) 389 log->Printf ("SBThread(%p)::GetStopReturnValue() => error: process is running", exe_ctx.GetThreadPtr()); 390 } 391 } 392 393 if (log) 394 log->Printf ("SBThread(%p)::GetStopReturnValue () => %s", exe_ctx.GetThreadPtr(), 395 return_valobj_sp.get() 396 ? return_valobj_sp->GetValueAsCString() 397 : "<no return value>"); 398 399 return SBValue (return_valobj_sp); 400} 401 402void 403SBThread::SetThread (const ThreadSP& lldb_object_sp) 404{ 405 m_opaque_sp->SetThreadSP (lldb_object_sp); 406} 407 408 409lldb::tid_t 410SBThread::GetThreadID () const 411{ 412 ThreadSP thread_sp(m_opaque_sp->GetThreadSP()); 413 if (thread_sp) 414 return thread_sp->GetID(); 415 return LLDB_INVALID_THREAD_ID; 416} 417 418uint32_t 419SBThread::GetIndexID () const 420{ 421 ThreadSP thread_sp(m_opaque_sp->GetThreadSP()); 422 if (thread_sp) 423 return thread_sp->GetIndexID(); 424 return LLDB_INVALID_INDEX32; 425} 426 427const char * 428SBThread::GetName () const 429{ 430 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 431 const char *name = NULL; 432 Mutex::Locker api_locker; 433 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 434 435 if (exe_ctx.HasThreadScope()) 436 { 437 Process::StopLocker stop_locker; 438 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 439 { 440 name = exe_ctx.GetThreadPtr()->GetName(); 441 } 442 else 443 { 444 if (log) 445 log->Printf ("SBThread(%p)::GetName() => error: process is running", exe_ctx.GetThreadPtr()); 446 } 447 } 448 449 if (log) 450 log->Printf ("SBThread(%p)::GetName () => %s", exe_ctx.GetThreadPtr(), name ? name : "NULL"); 451 452 return name; 453} 454 455const char * 456SBThread::GetQueueName () const 457{ 458 const char *name = NULL; 459 Mutex::Locker api_locker; 460 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 461 462 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 463 if (exe_ctx.HasThreadScope()) 464 { 465 Process::StopLocker stop_locker; 466 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 467 { 468 name = exe_ctx.GetThreadPtr()->GetQueueName(); 469 } 470 else 471 { 472 if (log) 473 log->Printf ("SBThread(%p)::GetQueueName() => error: process is running", exe_ctx.GetThreadPtr()); 474 } 475 } 476 477 if (log) 478 log->Printf ("SBThread(%p)::GetQueueName () => %s", exe_ctx.GetThreadPtr(), name ? name : "NULL"); 479 480 return name; 481} 482 483SBError 484SBThread::ResumeNewPlan (ExecutionContext &exe_ctx, ThreadPlan *new_plan) 485{ 486 SBError sb_error; 487 488 Process *process = exe_ctx.GetProcessPtr(); 489 if (!process) 490 { 491 sb_error.SetErrorString("No process in SBThread::ResumeNewPlan"); 492 return sb_error; 493 } 494 495 Thread *thread = exe_ctx.GetThreadPtr(); 496 if (!thread) 497 { 498 sb_error.SetErrorString("No thread in SBThread::ResumeNewPlan"); 499 return sb_error; 500 } 501 502 // User level plans should be Master Plans so they can be interrupted, other plans executed, and 503 // then a "continue" will resume the plan. 504 if (new_plan != NULL) 505 { 506 new_plan->SetIsMasterPlan(true); 507 new_plan->SetOkayToDiscard(false); 508 } 509 510 // Why do we need to set the current thread by ID here??? 511 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 512 sb_error.ref() = process->Resume(); 513 514 if (sb_error.Success()) 515 { 516 // If we are doing synchronous mode, then wait for the 517 // process to stop yet again! 518 if (process->GetTarget().GetDebugger().GetAsyncExecution () == false) 519 process->WaitForProcessToStop (NULL); 520 } 521 522 return sb_error; 523} 524 525void 526SBThread::StepOver (lldb::RunMode stop_other_threads) 527{ 528 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 529 530 Mutex::Locker api_locker; 531 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 532 533 534 if (log) 535 log->Printf ("SBThread(%p)::StepOver (stop_other_threads='%s')", exe_ctx.GetThreadPtr(), 536 Thread::RunModeAsCString (stop_other_threads)); 537 538 if (exe_ctx.HasThreadScope()) 539 { 540 Thread *thread = exe_ctx.GetThreadPtr(); 541 bool abort_other_plans = false; 542 StackFrameSP frame_sp(thread->GetStackFrameAtIndex (0)); 543 ThreadPlan *new_plan = NULL; 544 545 if (frame_sp) 546 { 547 if (frame_sp->HasDebugInformation ()) 548 { 549 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); 550 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, 551 eStepTypeOver, 552 sc.line_entry.range, 553 sc, 554 stop_other_threads, 555 false); 556 557 } 558 else 559 { 560 new_plan = thread->QueueThreadPlanForStepSingleInstruction (true, 561 abort_other_plans, 562 stop_other_threads); 563 } 564 } 565 566 // This returns an error, we should use it! 567 ResumeNewPlan (exe_ctx, new_plan); 568 } 569} 570 571void 572SBThread::StepInto (lldb::RunMode stop_other_threads) 573{ 574 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 575 576 Mutex::Locker api_locker; 577 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 578 579 if (log) 580 log->Printf ("SBThread(%p)::StepInto (stop_other_threads='%s')", exe_ctx.GetThreadPtr(), 581 Thread::RunModeAsCString (stop_other_threads)); 582 if (exe_ctx.HasThreadScope()) 583 { 584 bool abort_other_plans = false; 585 586 Thread *thread = exe_ctx.GetThreadPtr(); 587 StackFrameSP frame_sp(thread->GetStackFrameAtIndex (0)); 588 ThreadPlan *new_plan = NULL; 589 590 if (frame_sp && frame_sp->HasDebugInformation ()) 591 { 592 bool avoid_code_without_debug_info = true; 593 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); 594 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, 595 eStepTypeInto, 596 sc.line_entry.range, 597 sc, 598 stop_other_threads, 599 avoid_code_without_debug_info); 600 } 601 else 602 { 603 new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, 604 abort_other_plans, 605 stop_other_threads); 606 } 607 608 // This returns an error, we should use it! 609 ResumeNewPlan (exe_ctx, new_plan); 610 } 611} 612 613void 614SBThread::StepOut () 615{ 616 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 617 618 Mutex::Locker api_locker; 619 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 620 621 622 if (log) 623 log->Printf ("SBThread(%p)::StepOut ()", exe_ctx.GetThreadPtr()); 624 625 if (exe_ctx.HasThreadScope()) 626 { 627 bool abort_other_plans = false; 628 bool stop_other_threads = false; 629 630 Thread *thread = exe_ctx.GetThreadPtr(); 631 632 ThreadPlan *new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans, 633 NULL, 634 false, 635 stop_other_threads, 636 eVoteYes, 637 eVoteNoOpinion, 638 0); 639 640 // This returns an error, we should use it! 641 ResumeNewPlan (exe_ctx, new_plan); 642 } 643} 644 645void 646SBThread::StepOutOfFrame (lldb::SBFrame &sb_frame) 647{ 648 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 649 650 Mutex::Locker api_locker; 651 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 652 653 StackFrameSP frame_sp (sb_frame.GetFrameSP()); 654 if (log) 655 { 656 SBStream frame_desc_strm; 657 sb_frame.GetDescription (frame_desc_strm); 658 log->Printf ("SBThread(%p)::StepOutOfFrame (frame = SBFrame(%p): %s)", exe_ctx.GetThreadPtr(), frame_sp.get(), frame_desc_strm.GetData()); 659 } 660 661 if (exe_ctx.HasThreadScope()) 662 { 663 bool abort_other_plans = false; 664 bool stop_other_threads = false; 665 Thread *thread = exe_ctx.GetThreadPtr(); 666 667 ThreadPlan *new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans, 668 NULL, 669 false, 670 stop_other_threads, 671 eVoteYes, 672 eVoteNoOpinion, 673 frame_sp->GetFrameIndex()); 674 675 // This returns an error, we should use it! 676 ResumeNewPlan (exe_ctx, new_plan); 677 } 678} 679 680void 681SBThread::StepInstruction (bool step_over) 682{ 683 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 684 685 Mutex::Locker api_locker; 686 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 687 688 689 690 if (log) 691 log->Printf ("SBThread(%p)::StepInstruction (step_over=%i)", exe_ctx.GetThreadPtr(), step_over); 692 693 if (exe_ctx.HasThreadScope()) 694 { 695 Thread *thread = exe_ctx.GetThreadPtr(); 696 ThreadPlan *new_plan = thread->QueueThreadPlanForStepSingleInstruction (step_over, true, true); 697 698 // This returns an error, we should use it! 699 ResumeNewPlan (exe_ctx, new_plan); 700 } 701} 702 703void 704SBThread::RunToAddress (lldb::addr_t addr) 705{ 706 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 707 708 Mutex::Locker api_locker; 709 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 710 711 712 if (log) 713 log->Printf ("SBThread(%p)::RunToAddress (addr=0x%llx)", exe_ctx.GetThreadPtr(), addr); 714 715 if (exe_ctx.HasThreadScope()) 716 { 717 bool abort_other_plans = false; 718 bool stop_other_threads = true; 719 720 Address target_addr (addr); 721 722 Thread *thread = exe_ctx.GetThreadPtr(); 723 724 ThreadPlan *new_plan = thread->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads); 725 726 // This returns an error, we should use it! 727 ResumeNewPlan (exe_ctx, new_plan); 728 } 729} 730 731SBError 732SBThread::StepOverUntil (lldb::SBFrame &sb_frame, 733 lldb::SBFileSpec &sb_file_spec, 734 uint32_t line) 735{ 736 SBError sb_error; 737 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 738 char path[PATH_MAX]; 739 740 Mutex::Locker api_locker; 741 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 742 743 StackFrameSP frame_sp (sb_frame.GetFrameSP()); 744 745 if (log) 746 { 747 SBStream frame_desc_strm; 748 sb_frame.GetDescription (frame_desc_strm); 749 sb_file_spec->GetPath (path, sizeof(path)); 750 log->Printf ("SBThread(%p)::StepOverUntil (frame = SBFrame(%p): %s, file+line = %s:%u)", 751 exe_ctx.GetThreadPtr(), 752 frame_sp.get(), 753 frame_desc_strm.GetData(), 754 path, line); 755 } 756 757 if (exe_ctx.HasThreadScope()) 758 { 759 Target *target = exe_ctx.GetTargetPtr(); 760 Thread *thread = exe_ctx.GetThreadPtr(); 761 762 if (line == 0) 763 { 764 sb_error.SetErrorString("invalid line argument"); 765 return sb_error; 766 } 767 768 if (!frame_sp) 769 { 770 frame_sp = thread->GetSelectedFrame (); 771 if (!frame_sp) 772 frame_sp = thread->GetStackFrameAtIndex (0); 773 } 774 775 SymbolContext frame_sc; 776 if (!frame_sp) 777 { 778 sb_error.SetErrorString("no valid frames in thread to step"); 779 return sb_error; 780 } 781 782 // If we have a frame, get its line 783 frame_sc = frame_sp->GetSymbolContext (eSymbolContextCompUnit | 784 eSymbolContextFunction | 785 eSymbolContextLineEntry | 786 eSymbolContextSymbol ); 787 788 if (frame_sc.comp_unit == NULL) 789 { 790 sb_error.SetErrorStringWithFormat("frame %u doesn't have debug information", frame_sp->GetFrameIndex()); 791 return sb_error; 792 } 793 794 FileSpec step_file_spec; 795 if (sb_file_spec.IsValid()) 796 { 797 // The file spec passed in was valid, so use it 798 step_file_spec = sb_file_spec.ref(); 799 } 800 else 801 { 802 if (frame_sc.line_entry.IsValid()) 803 step_file_spec = frame_sc.line_entry.file; 804 else 805 { 806 sb_error.SetErrorString("invalid file argument or no file for frame"); 807 return sb_error; 808 } 809 } 810 811 // Grab the current function, then we will make sure the "until" address is 812 // within the function. We discard addresses that are out of the current 813 // function, and then if there are no addresses remaining, give an appropriate 814 // error message. 815 816 bool all_in_function = true; 817 AddressRange fun_range = frame_sc.function->GetAddressRange(); 818 819 std::vector<addr_t> step_over_until_addrs; 820 const bool abort_other_plans = false; 821 const bool stop_other_threads = false; 822 const bool check_inlines = true; 823 const bool exact = false; 824 825 SymbolContextList sc_list; 826 const uint32_t num_matches = frame_sc.comp_unit->ResolveSymbolContext (step_file_spec, 827 line, 828 check_inlines, 829 exact, 830 eSymbolContextLineEntry, 831 sc_list); 832 if (num_matches > 0) 833 { 834 SymbolContext sc; 835 for (uint32_t i=0; i<num_matches; ++i) 836 { 837 if (sc_list.GetContextAtIndex(i, sc)) 838 { 839 addr_t step_addr = sc.line_entry.range.GetBaseAddress().GetLoadAddress(target); 840 if (step_addr != LLDB_INVALID_ADDRESS) 841 { 842 if (fun_range.ContainsLoadAddress(step_addr, target)) 843 step_over_until_addrs.push_back(step_addr); 844 else 845 all_in_function = false; 846 } 847 } 848 } 849 } 850 851 if (step_over_until_addrs.empty()) 852 { 853 if (all_in_function) 854 { 855 step_file_spec.GetPath (path, sizeof(path)); 856 sb_error.SetErrorStringWithFormat("No line entries for %s:%u", path, line); 857 } 858 else 859 sb_error.SetErrorString ("step until target not in current function"); 860 } 861 else 862 { 863 ThreadPlan *new_plan = thread->QueueThreadPlanForStepUntil (abort_other_plans, 864 &step_over_until_addrs[0], 865 step_over_until_addrs.size(), 866 stop_other_threads, 867 frame_sp->GetFrameIndex()); 868 869 sb_error = ResumeNewPlan (exe_ctx, new_plan); 870 } 871 } 872 else 873 { 874 sb_error.SetErrorString("this SBThread object is invalid"); 875 } 876 return sb_error; 877} 878 879SBError 880SBThread::ReturnFromFrame (SBFrame &frame, SBValue &return_value) 881{ 882 SBError sb_error; 883 884 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 885 886 Mutex::Locker api_locker; 887 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 888 889 890 if (log) 891 log->Printf ("SBThread(%p)::ReturnFromFrame (frame=%d)", exe_ctx.GetThreadPtr(), frame.GetFrameID()); 892 893 if (exe_ctx.HasThreadScope()) 894 { 895 Thread *thread = exe_ctx.GetThreadPtr(); 896 sb_error.SetError (thread->ReturnFromFrame(frame.GetFrameSP(), return_value.GetSP())); 897 } 898 899 return sb_error; 900} 901 902 903bool 904SBThread::Suspend() 905{ 906 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 907 ExecutionContext exe_ctx (m_opaque_sp.get()); 908 bool result = false; 909 if (exe_ctx.HasThreadScope()) 910 { 911 Process::StopLocker stop_locker; 912 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 913 { 914 exe_ctx.GetThreadPtr()->SetResumeState (eStateSuspended); 915 result = true; 916 } 917 else 918 { 919 if (log) 920 log->Printf ("SBThread(%p)::Suspend() => error: process is running", exe_ctx.GetThreadPtr()); 921 } 922 } 923 if (log) 924 log->Printf ("SBThread(%p)::Suspend() => %i", exe_ctx.GetThreadPtr(), result); 925 return result; 926} 927 928bool 929SBThread::Resume () 930{ 931 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 932 ExecutionContext exe_ctx (m_opaque_sp.get()); 933 bool result = false; 934 if (exe_ctx.HasThreadScope()) 935 { 936 Process::StopLocker stop_locker; 937 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 938 { 939 exe_ctx.GetThreadPtr()->SetResumeState (eStateRunning); 940 result = true; 941 } 942 else 943 { 944 if (log) 945 log->Printf ("SBThread(%p)::Resume() => error: process is running", exe_ctx.GetThreadPtr()); 946 } 947 } 948 if (log) 949 log->Printf ("SBThread(%p)::Resume() => %i", exe_ctx.GetThreadPtr(), result); 950 return result; 951} 952 953bool 954SBThread::IsSuspended() 955{ 956 ExecutionContext exe_ctx (m_opaque_sp.get()); 957 if (exe_ctx.HasThreadScope()) 958 return exe_ctx.GetThreadPtr()->GetResumeState () == eStateSuspended; 959 return false; 960} 961 962SBProcess 963SBThread::GetProcess () 964{ 965 966 SBProcess sb_process; 967 ProcessSP process_sp; 968 ExecutionContext exe_ctx (m_opaque_sp.get()); 969 if (exe_ctx.HasThreadScope()) 970 { 971 // Have to go up to the target so we can get a shared pointer to our process... 972 sb_process.SetSP (exe_ctx.GetProcessSP()); 973 } 974 975 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 976 if (log) 977 { 978 SBStream frame_desc_strm; 979 sb_process.GetDescription (frame_desc_strm); 980 log->Printf ("SBThread(%p)::GetProcess () => SBProcess(%p): %s", exe_ctx.GetThreadPtr(), 981 process_sp.get(), frame_desc_strm.GetData()); 982 } 983 984 return sb_process; 985} 986 987uint32_t 988SBThread::GetNumFrames () 989{ 990 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 991 992 uint32_t num_frames = 0; 993 Mutex::Locker api_locker; 994 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 995 996 if (exe_ctx.HasThreadScope()) 997 { 998 Process::StopLocker stop_locker; 999 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 1000 { 1001 num_frames = exe_ctx.GetThreadPtr()->GetStackFrameCount(); 1002 } 1003 else 1004 { 1005 if (log) 1006 log->Printf ("SBThread(%p)::GetNumFrames() => error: process is running", exe_ctx.GetThreadPtr()); 1007 } 1008 } 1009 1010 if (log) 1011 log->Printf ("SBThread(%p)::GetNumFrames () => %u", exe_ctx.GetThreadPtr(), num_frames); 1012 1013 return num_frames; 1014} 1015 1016SBFrame 1017SBThread::GetFrameAtIndex (uint32_t idx) 1018{ 1019 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 1020 1021 SBFrame sb_frame; 1022 StackFrameSP frame_sp; 1023 Mutex::Locker api_locker; 1024 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 1025 1026 if (exe_ctx.HasThreadScope()) 1027 { 1028 Process::StopLocker stop_locker; 1029 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 1030 { 1031 frame_sp = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex (idx); 1032 sb_frame.SetFrameSP (frame_sp); 1033 } 1034 else 1035 { 1036 if (log) 1037 log->Printf ("SBThread(%p)::GetFrameAtIndex() => error: process is running", exe_ctx.GetThreadPtr()); 1038 } 1039 } 1040 1041 if (log) 1042 { 1043 SBStream frame_desc_strm; 1044 sb_frame.GetDescription (frame_desc_strm); 1045 log->Printf ("SBThread(%p)::GetFrameAtIndex (idx=%d) => SBFrame(%p): %s", 1046 exe_ctx.GetThreadPtr(), idx, frame_sp.get(), frame_desc_strm.GetData()); 1047 } 1048 1049 return sb_frame; 1050} 1051 1052lldb::SBFrame 1053SBThread::GetSelectedFrame () 1054{ 1055 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 1056 1057 SBFrame sb_frame; 1058 StackFrameSP frame_sp; 1059 Mutex::Locker api_locker; 1060 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 1061 1062 if (exe_ctx.HasThreadScope()) 1063 { 1064 Process::StopLocker stop_locker; 1065 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 1066 { 1067 frame_sp = exe_ctx.GetThreadPtr()->GetSelectedFrame (); 1068 sb_frame.SetFrameSP (frame_sp); 1069 } 1070 else 1071 { 1072 if (log) 1073 log->Printf ("SBThread(%p)::GetSelectedFrame() => error: process is running", exe_ctx.GetThreadPtr()); 1074 } 1075 } 1076 1077 if (log) 1078 { 1079 SBStream frame_desc_strm; 1080 sb_frame.GetDescription (frame_desc_strm); 1081 log->Printf ("SBThread(%p)::GetSelectedFrame () => SBFrame(%p): %s", 1082 exe_ctx.GetThreadPtr(), frame_sp.get(), frame_desc_strm.GetData()); 1083 } 1084 1085 return sb_frame; 1086} 1087 1088lldb::SBFrame 1089SBThread::SetSelectedFrame (uint32_t idx) 1090{ 1091 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 1092 1093 SBFrame sb_frame; 1094 StackFrameSP frame_sp; 1095 Mutex::Locker api_locker; 1096 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 1097 1098 if (exe_ctx.HasThreadScope()) 1099 { 1100 Process::StopLocker stop_locker; 1101 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 1102 { 1103 Thread *thread = exe_ctx.GetThreadPtr(); 1104 frame_sp = thread->GetStackFrameAtIndex (idx); 1105 if (frame_sp) 1106 { 1107 thread->SetSelectedFrame (frame_sp.get()); 1108 sb_frame.SetFrameSP (frame_sp); 1109 } 1110 } 1111 else 1112 { 1113 if (log) 1114 log->Printf ("SBThread(%p)::SetSelectedFrame() => error: process is running", exe_ctx.GetThreadPtr()); 1115 } 1116 } 1117 1118 if (log) 1119 { 1120 SBStream frame_desc_strm; 1121 sb_frame.GetDescription (frame_desc_strm); 1122 log->Printf ("SBThread(%p)::SetSelectedFrame (idx=%u) => SBFrame(%p): %s", 1123 exe_ctx.GetThreadPtr(), idx, frame_sp.get(), frame_desc_strm.GetData()); 1124 } 1125 return sb_frame; 1126} 1127 1128 1129bool 1130SBThread::operator == (const SBThread &rhs) const 1131{ 1132 return m_opaque_sp->GetThreadSP().get() == rhs.m_opaque_sp->GetThreadSP().get(); 1133} 1134 1135bool 1136SBThread::operator != (const SBThread &rhs) const 1137{ 1138 return m_opaque_sp->GetThreadSP().get() != rhs.m_opaque_sp->GetThreadSP().get(); 1139} 1140 1141bool 1142SBThread::GetDescription (SBStream &description) const 1143{ 1144 Stream &strm = description.ref(); 1145 1146 ExecutionContext exe_ctx (m_opaque_sp.get()); 1147 if (exe_ctx.HasThreadScope()) 1148 { 1149 strm.Printf("SBThread: tid = 0x%4.4llx", exe_ctx.GetThreadPtr()->GetID()); 1150 } 1151 else 1152 strm.PutCString ("No value"); 1153 1154 return true; 1155} 1156