SBThread.cpp revision be0cde978e34379e30c01c92858f8f037d80d388
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 StackFrameSP frame_sp; 769 if (!frame_sp) 770 { 771 frame_sp = thread->GetSelectedFrame (); 772 if (!frame_sp) 773 frame_sp = thread->GetStackFrameAtIndex (0); 774 } 775 776 SymbolContext frame_sc; 777 if (!frame_sp) 778 { 779 sb_error.SetErrorString("no valid frames in thread to step"); 780 return sb_error; 781 } 782 783 // If we have a frame, get its line 784 frame_sc = frame_sp->GetSymbolContext (eSymbolContextCompUnit | 785 eSymbolContextFunction | 786 eSymbolContextLineEntry | 787 eSymbolContextSymbol ); 788 789 if (frame_sc.comp_unit == NULL) 790 { 791 sb_error.SetErrorStringWithFormat("frame %u doesn't have debug information", frame_sp->GetFrameIndex()); 792 return sb_error; 793 } 794 795 FileSpec step_file_spec; 796 if (sb_file_spec.IsValid()) 797 { 798 // The file spec passed in was valid, so use it 799 step_file_spec = sb_file_spec.ref(); 800 } 801 else 802 { 803 if (frame_sc.line_entry.IsValid()) 804 step_file_spec = frame_sc.line_entry.file; 805 else 806 { 807 sb_error.SetErrorString("invalid file argument or no file for frame"); 808 return sb_error; 809 } 810 } 811 812 // Grab the current function, then we will make sure the "until" address is 813 // within the function. We discard addresses that are out of the current 814 // function, and then if there are no addresses remaining, give an appropriate 815 // error message. 816 817 bool all_in_function = true; 818 AddressRange fun_range = frame_sc.function->GetAddressRange(); 819 820 std::vector<addr_t> step_over_until_addrs; 821 const bool abort_other_plans = false; 822 const bool stop_other_threads = false; 823 const bool check_inlines = true; 824 const bool exact = false; 825 826 SymbolContextList sc_list; 827 const uint32_t num_matches = frame_sc.comp_unit->ResolveSymbolContext (step_file_spec, 828 line, 829 check_inlines, 830 exact, 831 eSymbolContextLineEntry, 832 sc_list); 833 if (num_matches > 0) 834 { 835 SymbolContext sc; 836 for (uint32_t i=0; i<num_matches; ++i) 837 { 838 if (sc_list.GetContextAtIndex(i, sc)) 839 { 840 addr_t step_addr = sc.line_entry.range.GetBaseAddress().GetLoadAddress(target); 841 if (step_addr != LLDB_INVALID_ADDRESS) 842 { 843 if (fun_range.ContainsLoadAddress(step_addr, target)) 844 step_over_until_addrs.push_back(step_addr); 845 else 846 all_in_function = false; 847 } 848 } 849 } 850 } 851 852 if (step_over_until_addrs.empty()) 853 { 854 if (all_in_function) 855 { 856 step_file_spec.GetPath (path, sizeof(path)); 857 sb_error.SetErrorStringWithFormat("No line entries for %s:%u", path, line); 858 } 859 else 860 sb_error.SetErrorString ("step until target not in current function"); 861 } 862 else 863 { 864 ThreadPlan *new_plan = thread->QueueThreadPlanForStepUntil (abort_other_plans, 865 &step_over_until_addrs[0], 866 step_over_until_addrs.size(), 867 stop_other_threads, 868 frame_sp->GetFrameIndex()); 869 870 sb_error = ResumeNewPlan (exe_ctx, new_plan); 871 } 872 } 873 else 874 { 875 sb_error.SetErrorString("this SBThread object is invalid"); 876 } 877 return sb_error; 878} 879 880SBError 881SBThread::ReturnFromFrame (SBFrame &frame, SBValue &return_value) 882{ 883 SBError sb_error; 884 885 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 886 887 Mutex::Locker api_locker; 888 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 889 890 891 if (log) 892 log->Printf ("SBThread(%p)::ReturnFromFrame (frame=%d)", exe_ctx.GetThreadPtr(), frame.GetFrameID()); 893 894 if (exe_ctx.HasThreadScope()) 895 { 896 Thread *thread = exe_ctx.GetThreadPtr(); 897 sb_error.SetError (thread->ReturnFromFrame(frame.GetFrameSP(), return_value.GetSP())); 898 } 899 900 return sb_error; 901} 902 903 904bool 905SBThread::Suspend() 906{ 907 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 908 ExecutionContext exe_ctx (m_opaque_sp.get()); 909 bool result = false; 910 if (exe_ctx.HasThreadScope()) 911 { 912 Process::StopLocker stop_locker; 913 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 914 { 915 exe_ctx.GetThreadPtr()->SetResumeState (eStateSuspended); 916 result = true; 917 } 918 else 919 { 920 if (log) 921 log->Printf ("SBThread(%p)::Suspend() => error: process is running", exe_ctx.GetThreadPtr()); 922 } 923 } 924 if (log) 925 log->Printf ("SBThread(%p)::Suspend() => %i", exe_ctx.GetThreadPtr(), result); 926 return result; 927} 928 929bool 930SBThread::Resume () 931{ 932 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 933 ExecutionContext exe_ctx (m_opaque_sp.get()); 934 bool result = false; 935 if (exe_ctx.HasThreadScope()) 936 { 937 Process::StopLocker stop_locker; 938 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 939 { 940 exe_ctx.GetThreadPtr()->SetResumeState (eStateRunning); 941 result = true; 942 } 943 else 944 { 945 if (log) 946 log->Printf ("SBThread(%p)::Resume() => error: process is running", exe_ctx.GetThreadPtr()); 947 } 948 } 949 if (log) 950 log->Printf ("SBThread(%p)::Resume() => %i", exe_ctx.GetThreadPtr(), result); 951 return result; 952} 953 954bool 955SBThread::IsSuspended() 956{ 957 ExecutionContext exe_ctx (m_opaque_sp.get()); 958 if (exe_ctx.HasThreadScope()) 959 return exe_ctx.GetThreadPtr()->GetResumeState () == eStateSuspended; 960 return false; 961} 962 963SBProcess 964SBThread::GetProcess () 965{ 966 967 SBProcess sb_process; 968 ProcessSP process_sp; 969 ExecutionContext exe_ctx (m_opaque_sp.get()); 970 if (exe_ctx.HasThreadScope()) 971 { 972 // Have to go up to the target so we can get a shared pointer to our process... 973 sb_process.SetSP (exe_ctx.GetProcessSP()); 974 } 975 976 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 977 if (log) 978 { 979 SBStream frame_desc_strm; 980 sb_process.GetDescription (frame_desc_strm); 981 log->Printf ("SBThread(%p)::GetProcess () => SBProcess(%p): %s", exe_ctx.GetThreadPtr(), 982 process_sp.get(), frame_desc_strm.GetData()); 983 } 984 985 return sb_process; 986} 987 988uint32_t 989SBThread::GetNumFrames () 990{ 991 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 992 993 uint32_t num_frames = 0; 994 Mutex::Locker api_locker; 995 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 996 997 if (exe_ctx.HasThreadScope()) 998 { 999 Process::StopLocker stop_locker; 1000 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 1001 { 1002 num_frames = exe_ctx.GetThreadPtr()->GetStackFrameCount(); 1003 } 1004 else 1005 { 1006 if (log) 1007 log->Printf ("SBThread(%p)::GetNumFrames() => error: process is running", exe_ctx.GetThreadPtr()); 1008 } 1009 } 1010 1011 if (log) 1012 log->Printf ("SBThread(%p)::GetNumFrames () => %u", exe_ctx.GetThreadPtr(), num_frames); 1013 1014 return num_frames; 1015} 1016 1017SBFrame 1018SBThread::GetFrameAtIndex (uint32_t idx) 1019{ 1020 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 1021 1022 SBFrame sb_frame; 1023 StackFrameSP frame_sp; 1024 Mutex::Locker api_locker; 1025 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 1026 1027 if (exe_ctx.HasThreadScope()) 1028 { 1029 Process::StopLocker stop_locker; 1030 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 1031 { 1032 frame_sp = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex (idx); 1033 sb_frame.SetFrameSP (frame_sp); 1034 } 1035 else 1036 { 1037 if (log) 1038 log->Printf ("SBThread(%p)::GetFrameAtIndex() => error: process is running", exe_ctx.GetThreadPtr()); 1039 } 1040 } 1041 1042 if (log) 1043 { 1044 SBStream frame_desc_strm; 1045 sb_frame.GetDescription (frame_desc_strm); 1046 log->Printf ("SBThread(%p)::GetFrameAtIndex (idx=%d) => SBFrame(%p): %s", 1047 exe_ctx.GetThreadPtr(), idx, frame_sp.get(), frame_desc_strm.GetData()); 1048 } 1049 1050 return sb_frame; 1051} 1052 1053lldb::SBFrame 1054SBThread::GetSelectedFrame () 1055{ 1056 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 1057 1058 SBFrame sb_frame; 1059 StackFrameSP frame_sp; 1060 Mutex::Locker api_locker; 1061 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 1062 1063 if (exe_ctx.HasThreadScope()) 1064 { 1065 Process::StopLocker stop_locker; 1066 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 1067 { 1068 frame_sp = exe_ctx.GetThreadPtr()->GetSelectedFrame (); 1069 sb_frame.SetFrameSP (frame_sp); 1070 } 1071 else 1072 { 1073 if (log) 1074 log->Printf ("SBThread(%p)::GetSelectedFrame() => error: process is running", exe_ctx.GetThreadPtr()); 1075 } 1076 } 1077 1078 if (log) 1079 { 1080 SBStream frame_desc_strm; 1081 sb_frame.GetDescription (frame_desc_strm); 1082 log->Printf ("SBThread(%p)::GetSelectedFrame () => SBFrame(%p): %s", 1083 exe_ctx.GetThreadPtr(), frame_sp.get(), frame_desc_strm.GetData()); 1084 } 1085 1086 return sb_frame; 1087} 1088 1089lldb::SBFrame 1090SBThread::SetSelectedFrame (uint32_t idx) 1091{ 1092 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 1093 1094 SBFrame sb_frame; 1095 StackFrameSP frame_sp; 1096 Mutex::Locker api_locker; 1097 ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); 1098 1099 if (exe_ctx.HasThreadScope()) 1100 { 1101 Process::StopLocker stop_locker; 1102 if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) 1103 { 1104 Thread *thread = exe_ctx.GetThreadPtr(); 1105 frame_sp = thread->GetStackFrameAtIndex (idx); 1106 if (frame_sp) 1107 { 1108 thread->SetSelectedFrame (frame_sp.get()); 1109 sb_frame.SetFrameSP (frame_sp); 1110 } 1111 } 1112 else 1113 { 1114 if (log) 1115 log->Printf ("SBThread(%p)::SetSelectedFrame() => error: process is running", exe_ctx.GetThreadPtr()); 1116 } 1117 } 1118 1119 if (log) 1120 { 1121 SBStream frame_desc_strm; 1122 sb_frame.GetDescription (frame_desc_strm); 1123 log->Printf ("SBThread(%p)::SetSelectedFrame (idx=%u) => SBFrame(%p): %s", 1124 exe_ctx.GetThreadPtr(), idx, frame_sp.get(), frame_desc_strm.GetData()); 1125 } 1126 return sb_frame; 1127} 1128 1129 1130bool 1131SBThread::operator == (const SBThread &rhs) const 1132{ 1133 return m_opaque_sp->GetThreadSP().get() == rhs.m_opaque_sp->GetThreadSP().get(); 1134} 1135 1136bool 1137SBThread::operator != (const SBThread &rhs) const 1138{ 1139 return m_opaque_sp->GetThreadSP().get() != rhs.m_opaque_sp->GetThreadSP().get(); 1140} 1141 1142bool 1143SBThread::GetDescription (SBStream &description) const 1144{ 1145 Stream &strm = description.ref(); 1146 1147 ExecutionContext exe_ctx (m_opaque_sp.get()); 1148 if (exe_ctx.HasThreadScope()) 1149 { 1150 strm.Printf("SBThread: tid = 0x%4.4llx", exe_ctx.GetThreadPtr()->GetID()); 1151 } 1152 else 1153 strm.PutCString ("No value"); 1154 1155 return true; 1156} 1157