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 176 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 177 178 if (bp_site_sp) 179 { 180 size_t num_owners = bp_site_sp->GetNumberOfOwners(); 181 182 if (num_owners == 0) 183 { 184 m_should_stop = true; 185 } 186 else 187 { 188 // We go through each location, and test first its condition. If the condition says to stop, 189 // then we run the callback for that location. If that callback says to stop as well, then 190 // we set m_should_stop to true; we are going to stop. 191 // But we still want to give all the breakpoints whose conditions say we are going to stop a 192 // chance to run their callbacks. 193 // Of course if any callback restarts the target by putting "continue" in the callback, then 194 // we're going to restart, without running the rest of the callbacks. And in this case we will 195 // end up not stopping even if another location said we should stop. But that's better than not 196 // running all the callbacks. 197 198 m_should_stop = false; 199 200 StoppointCallbackContext context (event_ptr, 201 &m_thread.GetProcess(), 202 &m_thread, 203 m_thread.GetStackFrameAtIndex(0).get(), 204 false); 205 206 for (size_t j = 0; j < num_owners; j++) 207 { 208 lldb::BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(j); 209 210 // First run the condition for the breakpoint. If that says we should stop, then we'll run 211 // the callback for the breakpoint. If the callback says we shouldn't stop that will win. 212 213 bool condition_says_stop = true; 214 if (bp_loc_sp->GetConditionText() != NULL) 215 { 216 // We need to make sure the user sees any parse errors in their condition, so we'll hook the 217 // constructor errors up to the debugger's Async I/O. 218 219 ValueObjectSP result_valobj_sp; 220 221 ExecutionResults result_code; 222 ValueObjectSP result_value_sp; 223 const bool discard_on_error = true; 224 Error error; 225 result_code = ClangUserExpression::EvaluateWithError (context.exe_ctx, 226 eExecutionPolicyAlways, 227 lldb::eLanguageTypeUnknown, 228 ClangUserExpression::eResultTypeAny, 229 discard_on_error, 230 bp_loc_sp->GetConditionText(), 231 NULL, 232 result_value_sp, 233 error); 234 if (result_code == eExecutionCompleted) 235 { 236 if (result_value_sp) 237 { 238 Scalar scalar_value; 239 if (result_value_sp->ResolveValue (scalar_value)) 240 { 241 if (scalar_value.ULongLong(1) == 0) 242 condition_says_stop = false; 243 else 244 condition_says_stop = true; 245 if (log) 246 log->Printf("Condition successfully evaluated, result is %s.\n", 247 m_should_stop ? "true" : "false"); 248 } 249 else 250 { 251 condition_says_stop = true; 252 if (log) 253 log->Printf("Failed to get an integer result from the expression."); 254 } 255 } 256 } 257 else 258 { 259 Debugger &debugger = context.exe_ctx.GetTargetRef().GetDebugger(); 260 StreamSP error_sp = debugger.GetAsyncErrorStream (); 261 error_sp->Printf ("Stopped due to an error evaluating condition of breakpoint "); 262 bp_loc_sp->GetDescription (error_sp.get(), eDescriptionLevelBrief); 263 error_sp->Printf (": \"%s\"", 264 bp_loc_sp->GetConditionText()); 265 error_sp->EOL(); 266 const char *err_str = error.AsCString("<Unknown Error>"); 267 if (log) 268 log->Printf("Error evaluating condition: \"%s\"\n", err_str); 269 270 error_sp->PutCString (err_str); 271 error_sp->EOL(); 272 error_sp->Flush(); 273 // If the condition fails to be parsed or run, we should stop. 274 condition_says_stop = true; 275 } 276 } 277 278 // If this location's condition says we should aren't going to stop, 279 // then don't run the callback for this location. 280 if (!condition_says_stop) 281 continue; 282 283 bool callback_says_stop; 284 285 // FIXME: For now the callbacks have to run in async mode - the first time we restart we need 286 // to get out of there. So set it here. 287 // When we figure out how to nest breakpoint hits then this will change. 288 289 Debugger &debugger = m_thread.GetProcess().GetTarget().GetDebugger(); 290 bool old_async = debugger.GetAsyncExecution(); 291 debugger.SetAsyncExecution (true); 292 293 callback_says_stop = bp_loc_sp->InvokeCallback (&context); 294 295 debugger.SetAsyncExecution (old_async); 296 297 if (callback_says_stop) 298 m_should_stop = true; 299 300 // Also make sure that the callback hasn't continued the target. 301 // If it did, when we'll set m_should_start to false and get out of here. 302 if (HasTargetRunSinceMe ()) 303 { 304 m_should_stop = false; 305 break; 306 } 307 } 308 } 309 // We've figured out what this stop wants to do, so mark it as valid so we don't compute it again. 310 m_should_stop_is_valid = true; 311 312 } 313 else 314 { 315 m_should_stop = true; 316 m_should_stop_is_valid = true; 317 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 318 319 if (log) 320 log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value); 321 } 322 if (log) 323 log->Printf ("Process::%s returning from action with m_should_stop: %d.", __FUNCTION__, m_should_stop); 324 } 325 326 virtual bool 327 ShouldNotify (Event *event_ptr) 328 { 329 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 330 if (bp_site_sp) 331 { 332 bool all_internal = true; 333 334 for (uint32_t i = 0; i < bp_site_sp->GetNumberOfOwners(); i++) 335 { 336 if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) 337 { 338 all_internal = false; 339 break; 340 } 341 } 342 return all_internal == false; 343 } 344 return true; 345 } 346 347 virtual const char * 348 GetDescription () 349 { 350 if (m_description.empty()) 351 { 352 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 353 if (bp_site_sp) 354 { 355 StreamString strm; 356 strm.Printf("breakpoint "); 357 bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief); 358 m_description.swap (strm.GetString()); 359 } 360 else 361 { 362 StreamString strm; 363 if (m_address == LLDB_INVALID_ADDRESS) 364 strm.Printf("breakpoint site %lli which has been deleted - unknown address", m_value); 365 else 366 strm.Printf("breakpoint site %lli which has been deleted - was at 0x%llx", m_value, m_address); 367 m_description.swap (strm.GetString()); 368 } 369 } 370 return m_description.c_str(); 371 } 372 373 private: 374 std::string m_description; 375 bool m_should_stop; 376 bool m_should_stop_is_valid; 377 bool m_should_perform_action; // Since we are trying to preserve the "state" of the system even if we run functions 378 // etc. behind the users backs, we need to make sure we only REALLY perform the action once. 379 lldb::addr_t m_address; // We use this to capture the breakpoint site address when we create the StopInfo, 380 // in case somebody deletes it between the time the StopInfo is made and the 381 // description is asked for. 382 }; 383 384 385 //---------------------------------------------------------------------- 386 // StopInfoWatchpoint 387 //---------------------------------------------------------------------- 388 389 class StopInfoWatchpoint : public StopInfo 390 { 391 public: 392 393 StopInfoWatchpoint (Thread &thread, break_id_t watch_id) : 394 StopInfo(thread, watch_id), 395 m_description(), 396 m_should_stop(false), 397 m_should_stop_is_valid(false) 398 { 399 } 400 401 virtual ~StopInfoWatchpoint () 402 { 403 } 404 405 virtual StopReason 406 GetStopReason () const 407 { 408 return eStopReasonWatchpoint; 409 } 410 411 virtual bool 412 ShouldStop (Event *event_ptr) 413 { 414 // ShouldStop() method is idempotent and should not affect hit count. 415 // See Process::RunPrivateStateThread()->Process()->HandlePrivateEvent() 416 // -->Process()::ShouldBroadcastEvent()->ThreadList::ShouldStop()-> 417 // Thread::ShouldStop()->ThreadPlanBase::ShouldStop()-> 418 // StopInfoWatchpoint::ShouldStop() and 419 // Event::DoOnRemoval()->Process::ProcessEventData::DoOnRemoval()-> 420 // StopInfoWatchpoint::PerformAction(). 421 if (m_should_stop_is_valid) 422 return m_should_stop; 423 424 WatchpointSP wp_sp = 425 m_thread.GetProcess().GetTarget().GetWatchpointList().FindByID(GetValue()); 426 if (wp_sp) 427 { 428 // Check if we should stop at a watchpoint. 429 StoppointCallbackContext context (event_ptr, 430 &m_thread.GetProcess(), 431 &m_thread, 432 m_thread.GetStackFrameAtIndex(0).get(), 433 true); 434 435 m_should_stop = wp_sp->ShouldStop (&context); 436 } 437 else 438 { 439 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 440 441 if (log) 442 log->Printf ("Process::%s could not find watchpoint location id: %lld...", 443 __FUNCTION__, GetValue()); 444 445 m_should_stop = true; 446 } 447 m_should_stop_is_valid = true; 448 return m_should_stop; 449 } 450 451 // Perform any action that is associated with this stop. This is done as the 452 // Event is removed from the event queue. 453 virtual void 454 PerformAction (Event *event_ptr) 455 { 456 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 457 // We're going to calculate if we should stop or not in some way during the course of 458 // this code. Also by default we're going to stop, so set that here. 459 m_should_stop = true; 460 461 WatchpointSP wp_sp = 462 m_thread.GetProcess().GetTarget().GetWatchpointList().FindByID(GetValue()); 463 if (wp_sp) 464 { 465 StoppointCallbackContext context (event_ptr, 466 &m_thread.GetProcess(), 467 &m_thread, 468 m_thread.GetStackFrameAtIndex(0).get(), 469 false); 470 bool stop_requested = wp_sp->InvokeCallback (&context); 471 // Also make sure that the callback hasn't continued the target. 472 // If it did, when we'll set m_should_start to false and get out of here. 473 if (HasTargetRunSinceMe ()) 474 m_should_stop = false; 475 476 if (m_should_stop && !stop_requested) 477 { 478 // We have been vetoed. 479 m_should_stop = false; 480 } 481 482 if (m_should_stop && wp_sp->GetConditionText() != NULL) 483 { 484 // We need to make sure the user sees any parse errors in their condition, so we'll hook the 485 // constructor errors up to the debugger's Async I/O. 486 StoppointCallbackContext context (event_ptr, 487 &m_thread.GetProcess(), 488 &m_thread, 489 m_thread.GetStackFrameAtIndex(0).get(), 490 false); 491 ExecutionResults result_code; 492 ValueObjectSP result_value_sp; 493 const bool discard_on_error = true; 494 Error error; 495 result_code = ClangUserExpression::EvaluateWithError (context.exe_ctx, 496 eExecutionPolicyAlways, 497 lldb::eLanguageTypeUnknown, 498 ClangUserExpression::eResultTypeAny, 499 discard_on_error, 500 wp_sp->GetConditionText(), 501 NULL, 502 result_value_sp, 503 error); 504 if (result_code == eExecutionCompleted) 505 { 506 if (result_value_sp) 507 { 508 Scalar scalar_value; 509 if (result_value_sp->ResolveValue (scalar_value)) 510 { 511 if (scalar_value.ULongLong(1) == 0) 512 { 513 // We have been vetoed. This takes precedence over querying 514 // the watchpoint whether it should stop (aka ignore count and 515 // friends). See also StopInfoWatchpoint::ShouldStop() as well 516 // as Process::ProcessEventData::DoOnRemoval(). 517 m_should_stop = false; 518 } 519 else 520 m_should_stop = true; 521 if (log) 522 log->Printf("Condition successfully evaluated, result is %s.\n", 523 m_should_stop ? "true" : "false"); 524 } 525 else 526 { 527 m_should_stop = true; 528 if (log) 529 log->Printf("Failed to get an integer result from the expression."); 530 } 531 } 532 } 533 else 534 { 535 Debugger &debugger = context.exe_ctx.GetTargetRef().GetDebugger(); 536 StreamSP error_sp = debugger.GetAsyncErrorStream (); 537 error_sp->Printf ("Stopped due to an error evaluating condition of watchpoint "); 538 wp_sp->GetDescription (error_sp.get(), eDescriptionLevelBrief); 539 error_sp->Printf (": \"%s\"", 540 wp_sp->GetConditionText()); 541 error_sp->EOL(); 542 const char *err_str = error.AsCString("<Unknown Error>"); 543 if (log) 544 log->Printf("Error evaluating condition: \"%s\"\n", err_str); 545 546 error_sp->PutCString (err_str); 547 error_sp->EOL(); 548 error_sp->Flush(); 549 // If the condition fails to be parsed or run, we should stop. 550 m_should_stop = true; 551 } 552 } 553 } 554 else 555 { 556 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 557 558 if (log) 559 log->Printf ("Process::%s could not find watchpoint id: %lld...", __FUNCTION__, m_value); 560 } 561 if (log) 562 log->Printf ("Process::%s returning from action with m_should_stop: %d.", __FUNCTION__, m_should_stop); 563 } 564 565 virtual const char * 566 GetDescription () 567 { 568 if (m_description.empty()) 569 { 570 StreamString strm; 571 strm.Printf("watchpoint %lli", m_value); 572 m_description.swap (strm.GetString()); 573 } 574 return m_description.c_str(); 575 } 576 577 private: 578 std::string m_description; 579 bool m_should_stop; 580 bool m_should_stop_is_valid; 581 }; 582 583 584 585 //---------------------------------------------------------------------- 586 // StopInfoUnixSignal 587 //---------------------------------------------------------------------- 588 589 class StopInfoUnixSignal : public StopInfo 590 { 591 public: 592 593 StopInfoUnixSignal (Thread &thread, int signo) : 594 StopInfo (thread, signo) 595 { 596 } 597 598 virtual ~StopInfoUnixSignal () 599 { 600 } 601 602 603 virtual StopReason 604 GetStopReason () const 605 { 606 return eStopReasonSignal; 607 } 608 609 virtual bool 610 ShouldStop (Event *event_ptr) 611 { 612 return m_thread.GetProcess().GetUnixSignals().GetShouldStop (m_value); 613 } 614 615 616 // If should stop returns false, check if we should notify of this event 617 virtual bool 618 ShouldNotify (Event *event_ptr) 619 { 620 return m_thread.GetProcess().GetUnixSignals().GetShouldNotify (m_value); 621 } 622 623 624 virtual void 625 WillResume (lldb::StateType resume_state) 626 { 627 if (m_thread.GetProcess().GetUnixSignals().GetShouldSuppress(m_value) == false) 628 m_thread.SetResumeSignal(m_value); 629 } 630 631 virtual const char * 632 GetDescription () 633 { 634 if (m_description.empty()) 635 { 636 StreamString strm; 637 const char *signal_name = m_thread.GetProcess().GetUnixSignals().GetSignalAsCString (m_value); 638 if (signal_name) 639 strm.Printf("signal %s", signal_name); 640 else 641 strm.Printf("signal %lli", m_value); 642 m_description.swap (strm.GetString()); 643 } 644 return m_description.c_str(); 645 } 646 }; 647 648 //---------------------------------------------------------------------- 649 // StopInfoTrace 650 //---------------------------------------------------------------------- 651 652 class StopInfoTrace : public StopInfo 653 { 654 public: 655 656 StopInfoTrace (Thread &thread) : 657 StopInfo (thread, LLDB_INVALID_UID) 658 { 659 } 660 661 virtual ~StopInfoTrace () 662 { 663 } 664 665 virtual StopReason 666 GetStopReason () const 667 { 668 return eStopReasonTrace; 669 } 670 671 virtual const char * 672 GetDescription () 673 { 674 if (m_description.empty()) 675 return "trace"; 676 else 677 return m_description.c_str(); 678 } 679 }; 680 681 682 //---------------------------------------------------------------------- 683 // StopInfoException 684 //---------------------------------------------------------------------- 685 686 class StopInfoException : public StopInfo 687 { 688 public: 689 690 StopInfoException (Thread &thread, const char *description) : 691 StopInfo (thread, LLDB_INVALID_UID) 692 { 693 if (description) 694 SetDescription (description); 695 } 696 697 virtual 698 ~StopInfoException () 699 { 700 } 701 702 virtual StopReason 703 GetStopReason () const 704 { 705 return eStopReasonException; 706 } 707 708 virtual const char * 709 GetDescription () 710 { 711 if (m_description.empty()) 712 return "exception"; 713 else 714 return m_description.c_str(); 715 } 716 }; 717 718 719 //---------------------------------------------------------------------- 720 // StopInfoThreadPlan 721 //---------------------------------------------------------------------- 722 723 class StopInfoThreadPlan : public StopInfo 724 { 725 public: 726 727 StopInfoThreadPlan (ThreadPlanSP &plan_sp, ValueObjectSP &return_valobj_sp) : 728 StopInfo (plan_sp->GetThread(), LLDB_INVALID_UID), 729 m_plan_sp (plan_sp), 730 m_return_valobj_sp (return_valobj_sp) 731 { 732 } 733 734 virtual ~StopInfoThreadPlan () 735 { 736 } 737 738 virtual StopReason 739 GetStopReason () const 740 { 741 return eStopReasonPlanComplete; 742 } 743 744 virtual const char * 745 GetDescription () 746 { 747 if (m_description.empty()) 748 { 749 StreamString strm; 750 m_plan_sp->GetDescription (&strm, eDescriptionLevelBrief); 751 m_description.swap (strm.GetString()); 752 } 753 return m_description.c_str(); 754 } 755 756 ValueObjectSP 757 GetReturnValueObject() 758 { 759 return m_return_valobj_sp; 760 } 761 762 private: 763 ThreadPlanSP m_plan_sp; 764 ValueObjectSP m_return_valobj_sp; 765 }; 766 } // namespace lldb_private 767 768 StopInfoSP 769 StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id) 770 { 771 return StopInfoSP (new StopInfoBreakpoint (thread, break_id)); 772 } 773 774 StopInfoSP 775 StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id, bool should_stop) 776 { 777 return StopInfoSP (new StopInfoBreakpoint (thread, break_id, should_stop)); 778 } 779 780 StopInfoSP 781 StopInfo::CreateStopReasonWithWatchpointID (Thread &thread, break_id_t watch_id) 782 { 783 return StopInfoSP (new StopInfoWatchpoint (thread, watch_id)); 784 } 785 786 StopInfoSP 787 StopInfo::CreateStopReasonWithSignal (Thread &thread, int signo) 788 { 789 return StopInfoSP (new StopInfoUnixSignal (thread, signo)); 790 } 791 792 StopInfoSP 793 StopInfo::CreateStopReasonToTrace (Thread &thread) 794 { 795 return StopInfoSP (new StopInfoTrace (thread)); 796 } 797 798 StopInfoSP 799 StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp, ValueObjectSP return_valobj_sp) 800 { 801 return StopInfoSP (new StopInfoThreadPlan (plan_sp, return_valobj_sp)); 802 } 803 804 StopInfoSP 805 StopInfo::CreateStopReasonWithException (Thread &thread, const char *description) 806 { 807 return StopInfoSP (new StopInfoException (thread, description)); 808 } 809 810 ValueObjectSP 811 StopInfo::GetReturnValueObject(StopInfoSP &stop_info_sp) 812 { 813 if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonPlanComplete) 814 { 815 StopInfoThreadPlan *plan_stop_info = static_cast<StopInfoThreadPlan *>(stop_info_sp.get()); 816 return plan_stop_info->GetReturnValueObject(); 817 } 818 else 819 return ValueObjectSP(); 820 } 821