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