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/Core/Debugger.h" 16 #include "lldb/Core/Stream.h" 17 #include "lldb/Core/StreamFile.h" 18 #include "lldb/Interpreter/CommandInterpreter.h" 19 #include "lldb/Target/Thread.h" 20 #include "lldb/Target/Process.h" 21 #include "lldb/Symbol/SymbolContext.h" 22 #include "lldb/Symbol/CompileUnit.h" 23 #include "lldb/Target/StopInfo.h" 24 #include "lldb/Target/Target.h" 25 #include "lldb/Target/ThreadPlan.h" 26 #include "lldb/Target/ThreadPlanStepInstruction.h" 27 #include "lldb/Target/ThreadPlanStepOut.h" 28 #include "lldb/Target/ThreadPlanStepRange.h" 29 #include "lldb/Target/ThreadPlanStepInRange.h" 30 31 32 #include "lldb/API/SBAddress.h" 33 #include "lldb/API/SBFrame.h" 34 #include "lldb/API/SBSourceManager.h" 35 #include "lldb/API/SBDebugger.h" 36 #include "lldb/API/SBProcess.h" 37 38 using namespace lldb; 39 using namespace lldb_private; 40 41 SBThread::SBThread () : 42 m_opaque_sp () 43 { 44 } 45 46 //---------------------------------------------------------------------- 47 // Thread constructor 48 //---------------------------------------------------------------------- 49 SBThread::SBThread (const ThreadSP& lldb_object_sp) : 50 m_opaque_sp (lldb_object_sp) 51 { 52 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API); 53 54 if (log) 55 { 56 SBStream sstr; 57 GetDescription (sstr); 58 log->Printf ("SBThread::SBThread (lldb_object_sp=%p) => this.sp = %p (%s)", 59 lldb_object_sp.get(), m_opaque_sp.get(), sstr.GetData()); 60 } 61 } 62 63 SBThread::SBThread (const SBThread &rhs) 64 { 65 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API); 66 67 m_opaque_sp = rhs.m_opaque_sp; 68 69 if (log) 70 log->Printf ("SBThread::SBThread (rhs.sp=%p) => this.sp = %p", 71 rhs.m_opaque_sp.get(), m_opaque_sp.get()); 72 73 } 74 75 //---------------------------------------------------------------------- 76 // Destructor 77 //---------------------------------------------------------------------- 78 SBThread::~SBThread() 79 { 80 } 81 82 bool 83 SBThread::IsValid() const 84 { 85 return m_opaque_sp != NULL; 86 } 87 88 void 89 SBThread::Clear () 90 { 91 m_opaque_sp.reset(); 92 } 93 94 95 StopReason 96 SBThread::GetStopReason() 97 { 98 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API); 99 100 //if (log) 101 // log->Printf ("SBThread::GetStopReason ()"); 102 103 StopReason reason = eStopReasonInvalid; 104 if (m_opaque_sp) 105 { 106 StopInfoSP stop_info_sp = m_opaque_sp->GetStopInfo (); 107 if (stop_info_sp) 108 reason = stop_info_sp->GetStopReason(); 109 } 110 111 if (log) 112 log->Printf ("SBThread::GetStopReason (this.sp=%p) => '%s'", m_opaque_sp.get(), 113 Thread::StopReasonAsCString (reason)); 114 115 return reason; 116 } 117 118 size_t 119 SBThread::GetStopDescription (char *dst, size_t dst_len) 120 { 121 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API); 122 123 //if (log) 124 // log->Printf ("SBThread::GetStopDescription (char *dst, size_t dst_len)"); 125 126 if (m_opaque_sp) 127 { 128 StopInfoSP stop_info_sp = m_opaque_sp->GetStopInfo (); 129 if (stop_info_sp) 130 { 131 const char *stop_desc = stop_info_sp->GetDescription(); 132 if (stop_desc) 133 { 134 if (log) 135 log->Printf ("SBThread::GetStopDescription (this.sp=%p, dst, dst_len) => '%s'", 136 m_opaque_sp.get(), stop_desc); 137 if (dst) 138 return ::snprintf (dst, dst_len, "%s", stop_desc); 139 else 140 { 141 // NULL dst passed in, return the length needed to contain the description 142 return ::strlen (stop_desc) + 1; // Include the NULL byte for size 143 } 144 } 145 else 146 { 147 size_t stop_desc_len = 0; 148 switch (stop_info_sp->GetStopReason()) 149 { 150 case eStopReasonTrace: 151 case eStopReasonPlanComplete: 152 { 153 static char trace_desc[] = "step"; 154 stop_desc = trace_desc; 155 stop_desc_len = sizeof(trace_desc); // Include the NULL byte for size 156 } 157 break; 158 159 case eStopReasonBreakpoint: 160 { 161 static char bp_desc[] = "breakpoint hit"; 162 stop_desc = bp_desc; 163 stop_desc_len = sizeof(bp_desc); // Include the NULL byte for size 164 } 165 break; 166 167 case eStopReasonWatchpoint: 168 { 169 static char wp_desc[] = "watchpoint hit"; 170 stop_desc = wp_desc; 171 stop_desc_len = sizeof(wp_desc); // Include the NULL byte for size 172 } 173 break; 174 175 case eStopReasonSignal: 176 { 177 stop_desc = m_opaque_sp->GetProcess().GetUnixSignals ().GetSignalAsCString (stop_info_sp->GetValue()); 178 if (stop_desc == NULL || stop_desc[0] == '\0') 179 { 180 static char signal_desc[] = "signal"; 181 stop_desc = signal_desc; 182 stop_desc_len = sizeof(signal_desc); // Include the NULL byte for size 183 } 184 } 185 break; 186 187 case eStopReasonException: 188 { 189 char exc_desc[] = "exception"; 190 stop_desc = exc_desc; 191 stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size 192 } 193 break; 194 195 default: 196 break; 197 } 198 199 if (stop_desc && stop_desc[0]) 200 { 201 if (log) 202 log->Printf ("SBThread::GetStopDescription (this.sp=%p, dst, dst_len) => '%s'", 203 m_opaque_sp.get(), stop_desc); 204 205 if (dst) 206 return ::snprintf (dst, dst_len, "%s", stop_desc) + 1; // Include the NULL byte 207 208 if (stop_desc_len == 0) 209 stop_desc_len = ::strlen (stop_desc) + 1; // Include the NULL byte 210 211 return stop_desc_len; 212 } 213 } 214 } 215 } 216 if (dst) 217 *dst = 0; 218 return 0; 219 } 220 221 void 222 SBThread::SetThread (const ThreadSP& lldb_object_sp) 223 { 224 m_opaque_sp = lldb_object_sp; 225 } 226 227 228 lldb::tid_t 229 SBThread::GetThreadID () const 230 { 231 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API); 232 233 //if (log) 234 // log->Printf ("SBThread::GetThreadID()"); 235 236 lldb::tid_t id = LLDB_INVALID_THREAD_ID; 237 if (m_opaque_sp) 238 id = m_opaque_sp->GetID(); 239 240 if (log) 241 log->Printf ("SBThread::GetThreadID (this.sp=%p) => %d", m_opaque_sp.get(), (uint32_t) id); 242 243 return id; 244 } 245 246 uint32_t 247 SBThread::GetIndexID () const 248 { 249 if (m_opaque_sp) 250 return m_opaque_sp->GetIndexID(); 251 return LLDB_INVALID_INDEX32; 252 } 253 const char * 254 SBThread::GetName () const 255 { 256 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API); 257 258 //if (log) 259 // log->Printf ("SBThread::GetName ()"); 260 261 if (m_opaque_sp) 262 { 263 if (log) 264 log->Printf ("SBThread::GetName (this.sp=%p) => '%s'", m_opaque_sp.get(), m_opaque_sp->GetName()); 265 return m_opaque_sp->GetName(); 266 } 267 268 if (log) 269 log->Printf ("SBThread::GetName (this.sp=%p) => NULL", m_opaque_sp.get()); 270 271 return NULL; 272 } 273 274 const char * 275 SBThread::GetQueueName () const 276 { 277 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API); 278 279 //if (log) 280 // log->Printf ("SBThread::GetQueueName ()"); 281 282 if (m_opaque_sp) 283 { 284 if (log) 285 log->Printf ("SBThread::GetQueueName (this.sp=%p) => '%s'", m_opaque_sp.get(), 286 m_opaque_sp->GetQueueName()); 287 return m_opaque_sp->GetQueueName(); 288 } 289 290 if (log) 291 log->Printf ("SBThread::GetQueueName (this.sp=%p) => NULL", m_opaque_sp.get()); 292 293 return NULL; 294 } 295 296 297 void 298 SBThread::StepOver (lldb::RunMode stop_other_threads) 299 { 300 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API); 301 302 if (log) 303 log->Printf ("SBThread::StepOver (this.sp=%p, stop_other_threads='%s')", m_opaque_sp.get(), 304 Thread::RunModeAsCString (stop_other_threads)); 305 306 if (m_opaque_sp) 307 { 308 bool abort_other_plans = true; 309 StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0)); 310 311 if (frame_sp) 312 { 313 if (frame_sp->HasDebugInformation ()) 314 { 315 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); 316 m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans, 317 eStepTypeOver, 318 sc.line_entry.range, 319 sc, 320 stop_other_threads, 321 false); 322 323 } 324 else 325 { 326 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (true, 327 abort_other_plans, 328 stop_other_threads); 329 } 330 } 331 332 Process &process = m_opaque_sp->GetProcess(); 333 // Why do we need to set the current thread by ID here??? 334 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 335 Error error (process.Resume()); 336 if (error.Success()) 337 { 338 // If we are doing synchronous mode, then wait for the 339 // process to stop yet again! 340 if (process.GetTarget().GetDebugger().GetAsyncExecution () == false) 341 process.WaitForProcessToStop (NULL); 342 } 343 } 344 } 345 346 void 347 SBThread::StepInto (lldb::RunMode stop_other_threads) 348 { 349 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API); 350 351 if (log) 352 log->Printf ("SBThread::StepInto (this.sp=%p, stop_other_threads='%s')", m_opaque_sp.get(), 353 Thread::RunModeAsCString (stop_other_threads)); 354 355 if (m_opaque_sp) 356 { 357 bool abort_other_plans = true; 358 359 StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0)); 360 361 if (frame_sp && frame_sp->HasDebugInformation ()) 362 { 363 bool avoid_code_without_debug_info = true; 364 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); 365 m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans, 366 eStepTypeInto, 367 sc.line_entry.range, 368 sc, 369 stop_other_threads, 370 avoid_code_without_debug_info); 371 } 372 else 373 { 374 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (false, 375 abort_other_plans, 376 stop_other_threads); 377 } 378 379 Process &process = m_opaque_sp->GetProcess(); 380 // Why do we need to set the current thread by ID here??? 381 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 382 Error error (process.Resume()); 383 if (error.Success()) 384 { 385 // If we are doing synchronous mode, then wait for the 386 // process to stop yet again! 387 if (process.GetTarget().GetDebugger().GetAsyncExecution () == false) 388 process.WaitForProcessToStop (NULL); 389 } 390 } 391 } 392 393 void 394 SBThread::StepOut () 395 { 396 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API); 397 398 if (log) 399 log->Printf ("SBThread::StepOut (this.sp=%p)", m_opaque_sp.get()); 400 401 if (m_opaque_sp) 402 { 403 bool abort_other_plans = true; 404 bool stop_other_threads = true; 405 406 m_opaque_sp->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, stop_other_threads, eVoteYes, eVoteNoOpinion); 407 408 Process &process = m_opaque_sp->GetProcess(); 409 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 410 Error error (process.Resume()); 411 if (error.Success()) 412 { 413 // If we are doing synchronous mode, then wait for the 414 // process to stop yet again! 415 if (process.GetTarget().GetDebugger().GetAsyncExecution () == false) 416 process.WaitForProcessToStop (NULL); 417 } 418 } 419 } 420 421 void 422 SBThread::StepInstruction (bool step_over) 423 { 424 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API); 425 426 if (log) 427 log->Printf ("SBThread::StepInstruction (this.sp=%p, step_over=%s)", m_opaque_sp.get(), 428 (step_over ? "true" : "false")); 429 430 if (m_opaque_sp) 431 { 432 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (step_over, true, true); 433 Process &process = m_opaque_sp->GetProcess(); 434 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 435 Error error (process.Resume()); 436 if (error.Success()) 437 { 438 // If we are doing synchronous mode, then wait for the 439 // process to stop yet again! 440 if (process.GetTarget().GetDebugger().GetAsyncExecution () == false) 441 process.WaitForProcessToStop (NULL); 442 } 443 } 444 } 445 446 void 447 SBThread::RunToAddress (lldb::addr_t addr) 448 { 449 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API); 450 451 if (log) 452 log->Printf ("SBThread::RunToAddress (this.sp=%p, addr=%p)", m_opaque_sp.get(), addr); 453 454 if (m_opaque_sp) 455 { 456 bool abort_other_plans = true; 457 bool stop_other_threads = true; 458 459 Address target_addr (NULL, addr); 460 461 m_opaque_sp->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads); 462 Process &process = m_opaque_sp->GetProcess(); 463 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 464 Error error (process.Resume()); 465 if (error.Success()) 466 { 467 // If we are doing synchronous mode, then wait for the 468 // process to stop yet again! 469 if (process.GetTarget().GetDebugger().GetAsyncExecution () == false) 470 process.WaitForProcessToStop (NULL); 471 } 472 } 473 474 } 475 476 SBProcess 477 SBThread::GetProcess () 478 { 479 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API); 480 481 //if (log) 482 // log->Printf ("SBThread::GetProcess ()"); 483 484 SBProcess process; 485 if (m_opaque_sp) 486 { 487 // Have to go up to the target so we can get a shared pointer to our process... 488 process.SetProcess(m_opaque_sp->GetProcess().GetTarget().GetProcessSP()); 489 } 490 491 if (log) 492 { 493 SBStream sstr; 494 process.GetDescription (sstr); 495 log->Printf ("SBThread::GetProcess (this.sp=%p) => SBProcess : this.sp = %p, '%s'", m_opaque_sp.get(), 496 process.get(), sstr.GetData()); 497 } 498 499 return process; 500 } 501 502 uint32_t 503 SBThread::GetNumFrames () 504 { 505 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API); 506 507 //if (log) 508 // log->Printf ("SBThread::GetNumFrames ()"); 509 510 uint32_t num_frames = 0; 511 if (m_opaque_sp) 512 num_frames = m_opaque_sp->GetStackFrameCount(); 513 514 if (log) 515 log->Printf ("SBThread::GetNumFrames (this.sp=%p) => %d", m_opaque_sp.get(), num_frames); 516 517 return num_frames; 518 } 519 520 SBFrame 521 SBThread::GetFrameAtIndex (uint32_t idx) 522 { 523 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API); 524 525 //if (log) 526 // log->Printf ("SBThread::GetFrameAtIndex (uint32_t idx) idx = %d", idx); 527 528 SBFrame sb_frame; 529 if (m_opaque_sp) 530 sb_frame.SetFrame (m_opaque_sp->GetStackFrameAtIndex (idx)); 531 532 if (log) 533 { 534 SBStream sstr; 535 sb_frame.GetDescription (sstr); 536 log->Printf ("SBThread::GetFrameAtIndex (this.sp=%p, idx=%d) => SBFrame.sp : this = %p, '%s'", 537 m_opaque_sp.get(), idx, sb_frame.get(), sstr.GetData()); 538 } 539 540 return sb_frame; 541 } 542 543 const lldb::SBThread & 544 SBThread::operator = (const lldb::SBThread &rhs) 545 { 546 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API); 547 548 if (log) 549 log->Printf ("SBThread::operator= (this.sp=%p, rhs.sp=%p)", m_opaque_sp.get(), rhs.m_opaque_sp.get()); 550 551 m_opaque_sp = rhs.m_opaque_sp; 552 return *this; 553 } 554 555 bool 556 SBThread::operator == (const SBThread &rhs) const 557 { 558 return m_opaque_sp.get() == rhs.m_opaque_sp.get(); 559 } 560 561 bool 562 SBThread::operator != (const SBThread &rhs) const 563 { 564 return m_opaque_sp.get() != rhs.m_opaque_sp.get(); 565 } 566 567 lldb_private::Thread * 568 SBThread::GetLLDBObjectPtr () 569 { 570 return m_opaque_sp.get(); 571 } 572 573 const lldb_private::Thread * 574 SBThread::operator->() const 575 { 576 return m_opaque_sp.get(); 577 } 578 579 const lldb_private::Thread & 580 SBThread::operator*() const 581 { 582 return *m_opaque_sp; 583 } 584 585 lldb_private::Thread * 586 SBThread::operator->() 587 { 588 return m_opaque_sp.get(); 589 } 590 591 lldb_private::Thread & 592 SBThread::operator*() 593 { 594 return *m_opaque_sp; 595 } 596 597 bool 598 SBThread::GetDescription (SBStream &description) 599 { 600 if (m_opaque_sp) 601 { 602 StreamString strm; 603 description.Printf("SBThread: tid = 0x%4.4x", m_opaque_sp->GetID()); 604 } 605 else 606 description.Printf ("No value"); 607 608 return true; 609 } 610 611 bool 612 SBThread::GetDescription (SBStream &description) const 613 { 614 if (m_opaque_sp) 615 { 616 StreamString strm; 617 description.Printf("SBThread: tid = 0x%4.4x", m_opaque_sp->GetID()); 618 } 619 else 620 description.Printf ("No value"); 621 622 return true; 623 } 624