1 //===-- StopInfo.cpp ---------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Target/StopInfo.h" 11 12 // C Includes 13 // C++ Includes 14 #include <string> 15 16 // Other libraries and framework includes 17 // Project includes 18 #include "lldb/Core/Log.h" 19 #include "lldb/Breakpoint/Breakpoint.h" 20 #include "lldb/Breakpoint/BreakpointLocation.h" 21 #include "lldb/Breakpoint/StoppointCallbackContext.h" 22 #include "lldb/Breakpoint/Watchpoint.h" 23 #include "lldb/Core/Debugger.h" 24 #include "lldb/Core/StreamString.h" 25 #include "lldb/Expression/ClangUserExpression.h" 26 #include "lldb/Target/Target.h" 27 #include "lldb/Target/Thread.h" 28 #include "lldb/Target/ThreadPlan.h" 29 #include "lldb/Target/Process.h" 30 #include "lldb/Target/UnixSignals.h" 31 32 using namespace lldb; 33 using namespace lldb_private; 34 35 StopInfo::StopInfo (Thread &thread, uint64_t value) : 36 m_thread (thread), 37 m_stop_id (thread.GetProcess().GetStopID()), 38 m_resume_id (thread.GetProcess().GetResumeID()), 39 m_value (value) 40 { 41 } 42 43 bool 44 StopInfo::IsValid () const 45 { 46 return m_thread.GetProcess().GetStopID() == m_stop_id; 47 } 48 49 void 50 StopInfo::MakeStopInfoValid () 51 { 52 m_stop_id = m_thread.GetProcess().GetStopID(); 53 m_resume_id = m_thread.GetProcess().GetResumeID(); 54 } 55 56 bool 57 StopInfo::HasTargetRunSinceMe () 58 { 59 lldb::StateType ret_type = m_thread.GetProcess().GetPrivateState(); 60 if (ret_type == eStateRunning) 61 { 62 return true; 63 } 64 else if (ret_type == eStateStopped) 65 { 66 // This is a little tricky. We want to count "run and stopped again before you could 67 // ask this question as a "TRUE" answer to HasTargetRunSinceMe. But we don't want to 68 // include any running of the target done for expressions. So we track both resumes, 69 // and resumes caused by expressions, and check if there are any resumes NOT caused 70 // by expressions. 71 72 uint32_t curr_resume_id = m_thread.GetProcess().GetResumeID(); 73 uint32_t last_user_expression_id = m_thread.GetProcess().GetLastUserExpressionResumeID (); 74 if (curr_resume_id == m_resume_id) 75 { 76 return false; 77 } 78 else if (curr_resume_id > last_user_expression_id) 79 { 80 return true; 81 } 82 } 83 return false; 84 } 85 86 //---------------------------------------------------------------------- 87 // StopInfoBreakpoint 88 //---------------------------------------------------------------------- 89 90 namespace lldb_private 91 { 92 class StopInfoBreakpoint : public StopInfo 93 { 94 public: 95 96 StopInfoBreakpoint (Thread &thread, break_id_t break_id) : 97 StopInfo (thread, break_id), 98 m_description(), 99 m_should_stop (false), 100 m_should_stop_is_valid (false), 101 m_should_perform_action (true), 102 m_address (LLDB_INVALID_ADDRESS) 103 { 104 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 105 if (bp_site_sp) 106 { 107 m_address = bp_site_sp->GetLoadAddress(); 108 } 109 } 110 111 StopInfoBreakpoint (Thread &thread, break_id_t break_id, bool should_stop) : 112 StopInfo (thread, break_id), 113 m_description(), 114 m_should_stop (should_stop), 115 m_should_stop_is_valid (true), 116 m_should_perform_action (true), 117 m_address (LLDB_INVALID_ADDRESS) 118 { 119 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 120 if (bp_site_sp) 121 { 122 m_address = bp_site_sp->GetLoadAddress(); 123 } 124 } 125 126 virtual ~StopInfoBreakpoint () 127 { 128 } 129 130 virtual StopReason 131 GetStopReason () const 132 { 133 return eStopReasonBreakpoint; 134 } 135 136 virtual bool 137 ShouldStop (Event *event_ptr) 138 { 139 if (!m_should_stop_is_valid) 140 { 141 // Only check once if we should stop at a breakpoint 142 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 143 if (bp_site_sp) 144 { 145 StoppointCallbackContext context (event_ptr, 146 &m_thread.GetProcess(), 147 &m_thread, 148 m_thread.GetStackFrameAtIndex(0).get(), 149 true); 150 151 m_should_stop = bp_site_sp->ShouldStop (&context); 152 } 153 else 154 { 155 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 156 157 if (log) 158 log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value); 159 160 m_should_stop = true; 161 } 162 m_should_stop_is_valid = true; 163 } 164 return m_should_stop; 165 } 166 167 virtual void 168 PerformAction (Event *event_ptr) 169 { 170 if (!m_should_perform_action) 171 return; 172 m_should_perform_action = false; 173 174 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 175 // We're going to calculate whether we should stop or not in some way during the course of 176 // this code. So set the valid flag here. Also by default we're going to stop, so 177 // set that here too. 178 // m_should_stop_is_valid = true; 179 m_should_stop = true; 180 181 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 182 if (bp_site_sp) 183 { 184 size_t num_owners = bp_site_sp->GetNumberOfOwners(); 185 186 // We only continue from the callbacks if ALL the callbacks want us to continue. 187 // However we want to run all the callbacks, except of course if one of them actually 188 // resumes the target. 189 // So we use stop_requested to track what we're were asked to do. 190 bool stop_requested = false; 191 for (size_t j = 0; j < num_owners; j++) 192 { 193 lldb::BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(j); 194 StoppointCallbackContext context (event_ptr, 195 &m_thread.GetProcess(), 196 &m_thread, 197 m_thread.GetStackFrameAtIndex(0).get(), 198 false); 199 bool callback_return; 200 201 // FIXME: For now the callbacks have to run in async mode - the first time we restart we need 202 // to get out of there. So set it here. 203 // When we figure out how to stack breakpoint hits then this will change. 204 205 Debugger &debugger = m_thread.GetProcess().GetTarget().GetDebugger(); 206 bool old_async = debugger.GetAsyncExecution(); 207 debugger.SetAsyncExecution (true); 208 209 callback_return = bp_loc_sp->InvokeCallback (&context); 210 211 debugger.SetAsyncExecution (old_async); 212 213 if (callback_return) 214 stop_requested = true; 215 216 // Also make sure that the callback hasn't continued the target. 217 // If it did, when we'll set m_should_start to false and get out of here. 218 if (HasTargetRunSinceMe ()) 219 { 220 m_should_stop = false; 221 break; 222 } 223 } 224 225 if (m_should_stop && !stop_requested) 226 { 227 m_should_stop_is_valid = true; 228 m_should_stop = false; 229 } 230 231 // Okay, so now if all the callbacks say we should stop, let's try the Conditions: 232 if (m_should_stop) 233 { 234 size_t num_owners = bp_site_sp->GetNumberOfOwners(); 235 for (size_t j = 0; j < num_owners; j++) 236 { 237 lldb::BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(j); 238 if (bp_loc_sp->GetConditionText() != NULL) 239 { 240 // We need to make sure the user sees any parse errors in their condition, so we'll hook the 241 // constructor errors up to the debugger's Async I/O. 242 243 StoppointCallbackContext context (event_ptr, 244 &m_thread.GetProcess(), 245 &m_thread, 246 m_thread.GetStackFrameAtIndex(0).get(), 247 false); 248 ValueObjectSP result_valobj_sp; 249 250 ExecutionResults result_code; 251 ValueObjectSP result_value_sp; 252 const bool discard_on_error = true; 253 Error error; 254 result_code = ClangUserExpression::EvaluateWithError (context.exe_ctx, 255 eExecutionPolicyAlways, 256 lldb::eLanguageTypeUnknown, 257 discard_on_error, 258 bp_loc_sp->GetConditionText(), 259 NULL, 260 result_value_sp, 261 error); 262 if (result_code == eExecutionCompleted) 263 { 264 if (result_value_sp) 265 { 266 Scalar scalar_value; 267 if (result_value_sp->ResolveValue (scalar_value)) 268 { 269 if (scalar_value.ULongLong(1) == 0) 270 m_should_stop = false; 271 else 272 m_should_stop = true; 273 if (log) 274 log->Printf("Condition successfully evaluated, result is %s.\n", 275 m_should_stop ? "true" : "false"); 276 } 277 else 278 { 279 m_should_stop = true; 280 if (log) 281 log->Printf("Failed to get an integer result from the expression."); 282 } 283 } 284 } 285 else 286 { 287 Debugger &debugger = context.exe_ctx.GetTargetRef().GetDebugger(); 288 StreamSP error_sp = debugger.GetAsyncErrorStream (); 289 error_sp->Printf ("Stopped due to an error evaluating condition of breakpoint "); 290 bp_loc_sp->GetDescription (error_sp.get(), eDescriptionLevelBrief); 291 error_sp->Printf (": \"%s\"", 292 bp_loc_sp->GetConditionText()); 293 error_sp->EOL(); 294 const char *err_str = error.AsCString("<Unknown Error>"); 295 if (log) 296 log->Printf("Error evaluating condition: \"%s\"\n", err_str); 297 298 error_sp->PutCString (err_str); 299 error_sp->EOL(); 300 error_sp->Flush(); 301 // If the condition fails to be parsed or run, we should stop. 302 m_should_stop = true; 303 } 304 } 305 306 // If any condition says we should stop, then we're going to stop, so we don't need 307 // to evaluate the others. 308 if (m_should_stop) 309 break; 310 } 311 } 312 } 313 else 314 { 315 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 316 317 if (log) 318 log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value); 319 } 320 if (log) 321 log->Printf ("Process::%s returning from action with m_should_stop: %d.", __FUNCTION__, m_should_stop); 322 } 323 324 virtual bool 325 ShouldNotify (Event *event_ptr) 326 { 327 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 328 if (bp_site_sp) 329 { 330 bool all_internal = true; 331 332 for (uint32_t i = 0; i < bp_site_sp->GetNumberOfOwners(); i++) 333 { 334 if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) 335 { 336 all_internal = false; 337 break; 338 } 339 } 340 return all_internal == false; 341 } 342 return true; 343 } 344 345 virtual const char * 346 GetDescription () 347 { 348 if (m_description.empty()) 349 { 350 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 351 if (bp_site_sp) 352 { 353 StreamString strm; 354 strm.Printf("breakpoint "); 355 bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief); 356 m_description.swap (strm.GetString()); 357 } 358 else 359 { 360 StreamString strm; 361 if (m_address == LLDB_INVALID_ADDRESS) 362 strm.Printf("breakpoint site %lli which has been deleted - unknown address", m_value); 363 else 364 strm.Printf("breakpoint site %lli which has been deleted - was at 0x%llx", m_value, m_address); 365 m_description.swap (strm.GetString()); 366 } 367 } 368 return m_description.c_str(); 369 } 370 371 private: 372 std::string m_description; 373 bool m_should_stop; 374 bool m_should_stop_is_valid; 375 bool m_should_perform_action; // Since we are trying to preserve the "state" of the system even if we run functions 376 // etc. behind the users backs, we need to make sure we only REALLY perform the action once. 377 lldb::addr_t m_address; // We use this to capture the breakpoint site address when we create the StopInfo, 378 // in case somebody deletes it between the time the StopInfo is made and the 379 // description is asked for. 380 }; 381 382 383 //---------------------------------------------------------------------- 384 // StopInfoWatchpoint 385 //---------------------------------------------------------------------- 386 387 class StopInfoWatchpoint : public StopInfo 388 { 389 public: 390 391 StopInfoWatchpoint (Thread &thread, break_id_t watch_id) : 392 StopInfo(thread, watch_id), 393 m_description(), 394 m_should_stop(false), 395 m_should_stop_is_valid(false) 396 { 397 } 398 399 virtual ~StopInfoWatchpoint () 400 { 401 } 402 403 virtual StopReason 404 GetStopReason () const 405 { 406 return eStopReasonWatchpoint; 407 } 408 409 virtual bool 410 ShouldStop (Event *event_ptr) 411 { 412 // ShouldStop() method is idempotent and should not affect hit count. 413 // See Process::RunPrivateStateThread()->Process()->HandlePrivateEvent() 414 // -->Process()::ShouldBroadcastEvent()->ThreadList::ShouldStop()-> 415 // Thread::ShouldStop()->ThreadPlanBase::ShouldStop()-> 416 // StopInfoWatchpoint::ShouldStop() and 417 // Event::DoOnRemoval()->Process::ProcessEventData::DoOnRemoval()-> 418 // StopInfoWatchpoint::PerformAction(). 419 if (m_should_stop_is_valid) 420 return m_should_stop; 421 422 WatchpointSP wp_sp = 423 m_thread.GetProcess().GetTarget().GetWatchpointList().FindByID(GetValue()); 424 if (wp_sp) 425 { 426 // Check if we should stop at a watchpoint. 427 StoppointCallbackContext context (event_ptr, 428 &m_thread.GetProcess(), 429 &m_thread, 430 m_thread.GetStackFrameAtIndex(0).get(), 431 true); 432 433 m_should_stop = wp_sp->ShouldStop (&context); 434 } 435 else 436 { 437 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 438 439 if (log) 440 log->Printf ("Process::%s could not find watchpoint location id: %lld...", 441 __FUNCTION__, GetValue()); 442 443 m_should_stop = true; 444 } 445 m_should_stop_is_valid = true; 446 return m_should_stop; 447 } 448 449 // Perform any action that is associated with this stop. This is done as the 450 // Event is removed from the event queue. 451 virtual void 452 PerformAction (Event *event_ptr) 453 { 454 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 455 // We're going to calculate if we should stop or not in some way during the course of 456 // this code. Also by default we're going to stop, so set that here. 457 m_should_stop = true; 458 459 WatchpointSP wp_sp = 460 m_thread.GetProcess().GetTarget().GetWatchpointList().FindByID(GetValue()); 461 if (wp_sp) 462 { 463 StoppointCallbackContext context (event_ptr, 464 &m_thread.GetProcess(), 465 &m_thread, 466 m_thread.GetStackFrameAtIndex(0).get(), 467 false); 468 bool stop_requested = wp_sp->InvokeCallback (&context); 469 // Also make sure that the callback hasn't continued the target. 470 // If it did, when we'll set m_should_start to false and get out of here. 471 if (HasTargetRunSinceMe ()) 472 m_should_stop = false; 473 474 if (m_should_stop && !stop_requested) 475 { 476 // We have been vetoed. 477 m_should_stop = false; 478 } 479 480 if (m_should_stop && wp_sp->GetConditionText() != NULL) 481 { 482 // We need to make sure the user sees any parse errors in their condition, so we'll hook the 483 // constructor errors up to the debugger's Async I/O. 484 StoppointCallbackContext context (event_ptr, 485 &m_thread.GetProcess(), 486 &m_thread, 487 m_thread.GetStackFrameAtIndex(0).get(), 488 false); 489 ExecutionResults result_code; 490 ValueObjectSP result_value_sp; 491 const bool discard_on_error = true; 492 Error error; 493 result_code = ClangUserExpression::EvaluateWithError (context.exe_ctx, 494 eExecutionPolicyAlways, 495 lldb::eLanguageTypeUnknown, 496 discard_on_error, 497 wp_sp->GetConditionText(), 498 NULL, 499 result_value_sp, 500 error); 501 if (result_code == eExecutionCompleted) 502 { 503 if (result_value_sp) 504 { 505 Scalar scalar_value; 506 if (result_value_sp->ResolveValue (scalar_value)) 507 { 508 if (scalar_value.ULongLong(1) == 0) 509 { 510 // We have been vetoed. This takes precedence over querying 511 // the watchpoint whether it should stop (aka ignore count and 512 // friends). See also StopInfoWatchpoint::ShouldStop() as well 513 // as Process::ProcessEventData::DoOnRemoval(). 514 m_should_stop = false; 515 } 516 else 517 m_should_stop = true; 518 if (log) 519 log->Printf("Condition successfully evaluated, result is %s.\n", 520 m_should_stop ? "true" : "false"); 521 } 522 else 523 { 524 m_should_stop = true; 525 if (log) 526 log->Printf("Failed to get an integer result from the expression."); 527 } 528 } 529 } 530 else 531 { 532 Debugger &debugger = context.exe_ctx.GetTargetRef().GetDebugger(); 533 StreamSP error_sp = debugger.GetAsyncErrorStream (); 534 error_sp->Printf ("Stopped due to an error evaluating condition of breakpoint "); 535 wp_sp->GetDescription (error_sp.get(), eDescriptionLevelBrief); 536 error_sp->Printf (": \"%s\"", 537 wp_sp->GetConditionText()); 538 error_sp->EOL(); 539 const char *err_str = error.AsCString("<Unknown Error>"); 540 if (log) 541 log->Printf("Error evaluating condition: \"%s\"\n", err_str); 542 543 error_sp->PutCString (err_str); 544 error_sp->EOL(); 545 error_sp->Flush(); 546 // If the condition fails to be parsed or run, we should stop. 547 m_should_stop = true; 548 } 549 } 550 } 551 else 552 { 553 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 554 555 if (log) 556 log->Printf ("Process::%s could not find watchpoint id: %lld...", __FUNCTION__, m_value); 557 } 558 if (log) 559 log->Printf ("Process::%s returning from action with m_should_stop: %d.", __FUNCTION__, m_should_stop); 560 } 561 562 virtual const char * 563 GetDescription () 564 { 565 if (m_description.empty()) 566 { 567 StreamString strm; 568 strm.Printf("watchpoint %lli", m_value); 569 m_description.swap (strm.GetString()); 570 } 571 return m_description.c_str(); 572 } 573 574 private: 575 std::string m_description; 576 bool m_should_stop; 577 bool m_should_stop_is_valid; 578 }; 579 580 581 582 //---------------------------------------------------------------------- 583 // StopInfoUnixSignal 584 //---------------------------------------------------------------------- 585 586 class StopInfoUnixSignal : public StopInfo 587 { 588 public: 589 590 StopInfoUnixSignal (Thread &thread, int signo) : 591 StopInfo (thread, signo) 592 { 593 } 594 595 virtual ~StopInfoUnixSignal () 596 { 597 } 598 599 600 virtual StopReason 601 GetStopReason () const 602 { 603 return eStopReasonSignal; 604 } 605 606 virtual bool 607 ShouldStop (Event *event_ptr) 608 { 609 return m_thread.GetProcess().GetUnixSignals().GetShouldStop (m_value); 610 } 611 612 613 // If should stop returns false, check if we should notify of this event 614 virtual bool 615 ShouldNotify (Event *event_ptr) 616 { 617 return m_thread.GetProcess().GetUnixSignals().GetShouldNotify (m_value); 618 } 619 620 621 virtual void 622 WillResume (lldb::StateType resume_state) 623 { 624 if (m_thread.GetProcess().GetUnixSignals().GetShouldSuppress(m_value) == false) 625 m_thread.SetResumeSignal(m_value); 626 } 627 628 virtual const char * 629 GetDescription () 630 { 631 if (m_description.empty()) 632 { 633 StreamString strm; 634 const char *signal_name = m_thread.GetProcess().GetUnixSignals().GetSignalAsCString (m_value); 635 if (signal_name) 636 strm.Printf("signal %s", signal_name); 637 else 638 strm.Printf("signal %lli", m_value); 639 m_description.swap (strm.GetString()); 640 } 641 return m_description.c_str(); 642 } 643 }; 644 645 //---------------------------------------------------------------------- 646 // StopInfoTrace 647 //---------------------------------------------------------------------- 648 649 class StopInfoTrace : public StopInfo 650 { 651 public: 652 653 StopInfoTrace (Thread &thread) : 654 StopInfo (thread, LLDB_INVALID_UID) 655 { 656 } 657 658 virtual ~StopInfoTrace () 659 { 660 } 661 662 virtual StopReason 663 GetStopReason () const 664 { 665 return eStopReasonTrace; 666 } 667 668 virtual const char * 669 GetDescription () 670 { 671 if (m_description.empty()) 672 return "trace"; 673 else 674 return m_description.c_str(); 675 } 676 }; 677 678 679 //---------------------------------------------------------------------- 680 // StopInfoException 681 //---------------------------------------------------------------------- 682 683 class StopInfoException : public StopInfo 684 { 685 public: 686 687 StopInfoException (Thread &thread, const char *description) : 688 StopInfo (thread, LLDB_INVALID_UID) 689 { 690 if (description) 691 SetDescription (description); 692 } 693 694 virtual 695 ~StopInfoException () 696 { 697 } 698 699 virtual StopReason 700 GetStopReason () const 701 { 702 return eStopReasonException; 703 } 704 705 virtual const char * 706 GetDescription () 707 { 708 if (m_description.empty()) 709 return "exception"; 710 else 711 return m_description.c_str(); 712 } 713 }; 714 715 716 //---------------------------------------------------------------------- 717 // StopInfoThreadPlan 718 //---------------------------------------------------------------------- 719 720 class StopInfoThreadPlan : public StopInfo 721 { 722 public: 723 724 StopInfoThreadPlan (ThreadPlanSP &plan_sp) : 725 StopInfo (plan_sp->GetThread(), LLDB_INVALID_UID), 726 m_plan_sp (plan_sp) 727 { 728 } 729 730 virtual ~StopInfoThreadPlan () 731 { 732 } 733 734 virtual StopReason 735 GetStopReason () const 736 { 737 return eStopReasonPlanComplete; 738 } 739 740 virtual const char * 741 GetDescription () 742 { 743 if (m_description.empty()) 744 { 745 StreamString strm; 746 m_plan_sp->GetDescription (&strm, eDescriptionLevelBrief); 747 m_description.swap (strm.GetString()); 748 } 749 return m_description.c_str(); 750 } 751 752 private: 753 ThreadPlanSP m_plan_sp; 754 }; 755 } // namespace lldb_private 756 757 StopInfoSP 758 StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id) 759 { 760 return StopInfoSP (new StopInfoBreakpoint (thread, break_id)); 761 } 762 763 StopInfoSP 764 StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id, bool should_stop) 765 { 766 return StopInfoSP (new StopInfoBreakpoint (thread, break_id, should_stop)); 767 } 768 769 StopInfoSP 770 StopInfo::CreateStopReasonWithWatchpointID (Thread &thread, break_id_t watch_id) 771 { 772 return StopInfoSP (new StopInfoWatchpoint (thread, watch_id)); 773 } 774 775 StopInfoSP 776 StopInfo::CreateStopReasonWithSignal (Thread &thread, int signo) 777 { 778 return StopInfoSP (new StopInfoUnixSignal (thread, signo)); 779 } 780 781 StopInfoSP 782 StopInfo::CreateStopReasonToTrace (Thread &thread) 783 { 784 return StopInfoSP (new StopInfoTrace (thread)); 785 } 786 787 StopInfoSP 788 StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp) 789 { 790 return StopInfoSP (new StopInfoThreadPlan (plan_sp)); 791 } 792 793 StopInfoSP 794 StopInfo::CreateStopReasonWithException (Thread &thread, const char *description) 795 { 796 return StopInfoSP (new StopInfoException (thread, description)); 797 } 798