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/WatchpointLocation.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_value (value) 39 { 40 } 41 42 bool 43 StopInfo::IsValid () const 44 { 45 return m_thread.GetProcess().GetStopID() == m_stop_id; 46 } 47 48 void 49 StopInfo::MakeStopInfoValid () 50 { 51 m_stop_id = m_thread.GetProcess().GetStopID(); 52 } 53 54 lldb::StateType 55 StopInfo::GetPrivateState () 56 { 57 return m_thread.GetProcess().GetPrivateState(); 58 } 59 60 //---------------------------------------------------------------------- 61 // StopInfoBreakpoint 62 //---------------------------------------------------------------------- 63 64 namespace lldb_private 65 { 66 class StopInfoBreakpoint : public StopInfo 67 { 68 public: 69 70 StopInfoBreakpoint (Thread &thread, break_id_t break_id) : 71 StopInfo (thread, break_id), 72 m_description(), 73 m_should_stop (false), 74 m_should_stop_is_valid (false), 75 m_should_perform_action (true) 76 { 77 } 78 79 StopInfoBreakpoint (Thread &thread, break_id_t break_id, bool should_stop) : 80 StopInfo (thread, break_id), 81 m_description(), 82 m_should_stop (should_stop), 83 m_should_stop_is_valid (true), 84 m_should_perform_action (true) 85 { 86 } 87 88 virtual ~StopInfoBreakpoint () 89 { 90 } 91 92 virtual StopReason 93 GetStopReason () const 94 { 95 return eStopReasonBreakpoint; 96 } 97 98 virtual bool 99 ShouldStop (Event *event_ptr) 100 { 101 if (!m_should_stop_is_valid) 102 { 103 // Only check once if we should stop at a breakpoint 104 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 105 if (bp_site_sp) 106 { 107 StoppointCallbackContext context (event_ptr, 108 &m_thread.GetProcess(), 109 &m_thread, 110 m_thread.GetStackFrameAtIndex(0).get(), 111 true); 112 113 m_should_stop = bp_site_sp->ShouldStop (&context); 114 } 115 else 116 { 117 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 118 119 if (log) 120 log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value); 121 122 m_should_stop = true; 123 } 124 m_should_stop_is_valid = true; 125 } 126 return m_should_stop; 127 } 128 129 virtual void 130 PerformAction (Event *event_ptr) 131 { 132 if (!m_should_perform_action) 133 return; 134 m_should_perform_action = false; 135 136 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 137 // We're going to calculate whether we should stop or not in some way during the course of 138 // this code. So set the valid flag here. Also by default we're going to stop, so 139 // set that here too. 140 // m_should_stop_is_valid = true; 141 m_should_stop = true; 142 143 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 144 if (bp_site_sp) 145 { 146 size_t num_owners = bp_site_sp->GetNumberOfOwners(); 147 148 // We only continue from the callbacks if ALL the callbacks want us to continue. 149 // However we want to run all the callbacks, except of course if one of them actually 150 // resumes the target. 151 // So we use stop_requested to track what we're were asked to do. 152 bool stop_requested = true; 153 for (size_t j = 0; j < num_owners; j++) 154 { 155 lldb::BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(j); 156 StoppointCallbackContext context (event_ptr, 157 &m_thread.GetProcess(), 158 &m_thread, 159 m_thread.GetStackFrameAtIndex(0).get(), 160 false); 161 stop_requested = bp_loc_sp->InvokeCallback (&context); 162 // Also make sure that the callback hasn't continued the target. 163 // If it did, when we'll set m_should_start to false and get out of here. 164 if (GetPrivateState() == eStateRunning) 165 m_should_stop = false; 166 } 167 168 if (m_should_stop && !stop_requested) 169 { 170 m_should_stop_is_valid = true; 171 m_should_stop = false; 172 } 173 174 // Okay, so now if all the callbacks say we should stop, let's try the Conditions: 175 if (m_should_stop) 176 { 177 size_t num_owners = bp_site_sp->GetNumberOfOwners(); 178 for (size_t j = 0; j < num_owners; j++) 179 { 180 lldb::BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(j); 181 if (bp_loc_sp->GetConditionText() != NULL) 182 { 183 // We need to make sure the user sees any parse errors in their condition, so we'll hook the 184 // constructor errors up to the debugger's Async I/O. 185 186 StoppointCallbackContext context (event_ptr, 187 &m_thread.GetProcess(), 188 &m_thread, 189 m_thread.GetStackFrameAtIndex(0).get(), 190 false); 191 ValueObjectSP result_valobj_sp; 192 193 ExecutionResults result_code; 194 ValueObjectSP result_value_sp; 195 const bool discard_on_error = true; 196 Error error; 197 result_code = ClangUserExpression::EvaluateWithError (context.exe_ctx, 198 eExecutionPolicyAlways, 199 discard_on_error, 200 bp_loc_sp->GetConditionText(), 201 NULL, 202 result_value_sp, 203 error); 204 if (result_code == eExecutionCompleted) 205 { 206 if (result_value_sp) 207 { 208 Scalar scalar_value; 209 if (result_value_sp->ResolveValue (scalar_value)) 210 { 211 if (scalar_value.ULongLong(1) == 0) 212 m_should_stop = false; 213 else 214 m_should_stop = true; 215 if (log) 216 log->Printf("Condition successfully evaluated, result is %s.\n", 217 m_should_stop ? "true" : "false"); 218 } 219 else 220 { 221 m_should_stop = true; 222 if (log) 223 log->Printf("Failed to get an integer result from the expression."); 224 } 225 } 226 } 227 else 228 { 229 Debugger &debugger = context.exe_ctx.GetTargetRef().GetDebugger(); 230 StreamSP error_sp = debugger.GetAsyncErrorStream (); 231 error_sp->Printf ("Stopped due to an error evaluating condition of breakpoint "); 232 bp_loc_sp->GetDescription (error_sp.get(), eDescriptionLevelBrief); 233 error_sp->Printf (": \"%s\"", 234 bp_loc_sp->GetConditionText()); 235 error_sp->EOL(); 236 const char *err_str = error.AsCString("<Unknown Error>"); 237 if (log) 238 log->Printf("Error evaluating condition: \"%s\"\n", err_str); 239 240 error_sp->PutCString (err_str); 241 error_sp->EOL(); 242 error_sp->Flush(); 243 // If the condition fails to be parsed or run, we should stop. 244 m_should_stop = true; 245 } 246 } 247 248 // If any condition says we should stop, then we're going to stop, so we don't need 249 // to evaluate the others. 250 if (m_should_stop) 251 break; 252 } 253 } 254 } 255 else 256 { 257 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 258 259 if (log) 260 log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value); 261 } 262 if (log) 263 log->Printf ("Process::%s returning from action with m_should_stop: %d.", __FUNCTION__, m_should_stop); 264 } 265 266 virtual bool 267 ShouldNotify (Event *event_ptr) 268 { 269 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 270 if (bp_site_sp) 271 { 272 bool all_internal = true; 273 274 for (uint32_t i = 0; i < bp_site_sp->GetNumberOfOwners(); i++) 275 { 276 if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) 277 { 278 all_internal = false; 279 break; 280 } 281 } 282 return all_internal == false; 283 } 284 return true; 285 } 286 287 virtual const char * 288 GetDescription () 289 { 290 if (m_description.empty()) 291 { 292 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 293 if (bp_site_sp) 294 { 295 StreamString strm; 296 strm.Printf("breakpoint "); 297 bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief); 298 m_description.swap (strm.GetString()); 299 } 300 else 301 { 302 StreamString strm; 303 strm.Printf("breakpoint site %lli", m_value); 304 m_description.swap (strm.GetString()); 305 } 306 } 307 return m_description.c_str(); 308 } 309 310 private: 311 std::string m_description; 312 bool m_should_stop; 313 bool m_should_stop_is_valid; 314 bool m_should_perform_action; // Since we are trying to preserve the "state" of the system even if we run functions 315 // etc. behind the users backs, we need to make sure we only REALLY perform the action once. 316 }; 317 318 319 //---------------------------------------------------------------------- 320 // StopInfoWatchpoint 321 //---------------------------------------------------------------------- 322 323 class StopInfoWatchpoint : public StopInfo 324 { 325 public: 326 327 StopInfoWatchpoint (Thread &thread, break_id_t watch_id) : 328 StopInfo(thread, watch_id), 329 m_description(), 330 m_should_stop(false), 331 m_should_stop_is_valid(false) 332 { 333 } 334 335 virtual ~StopInfoWatchpoint () 336 { 337 } 338 339 virtual StopReason 340 GetStopReason () const 341 { 342 return eStopReasonWatchpoint; 343 } 344 345 virtual bool 346 ShouldStop (Event *event_ptr) 347 { 348 // ShouldStop() method is idempotent and should not affect hit count. 349 if (m_should_stop_is_valid) 350 return m_should_stop; 351 352 WatchpointLocationSP wp_loc_sp = 353 m_thread.GetProcess().GetTarget().GetWatchpointLocationList().FindByID(GetValue()); 354 if (wp_loc_sp) 355 { 356 // Check if we should stop at a watchpoint. 357 StoppointCallbackContext context (event_ptr, 358 &m_thread.GetProcess(), 359 &m_thread, 360 m_thread.GetStackFrameAtIndex(0).get(), 361 true); 362 363 m_should_stop = wp_loc_sp->ShouldStop (&context); 364 } 365 else 366 { 367 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 368 369 if (log) 370 log->Printf ("Process::%s could not find watchpoint location id: %lld...", 371 __FUNCTION__, GetValue()); 372 373 m_should_stop = true; 374 } 375 m_should_stop_is_valid = true; 376 return m_should_stop; 377 } 378 379 virtual const char * 380 GetDescription () 381 { 382 if (m_description.empty()) 383 { 384 StreamString strm; 385 strm.Printf("watchpoint %lli", m_value); 386 m_description.swap (strm.GetString()); 387 } 388 return m_description.c_str(); 389 } 390 391 private: 392 std::string m_description; 393 bool m_should_stop; 394 bool m_should_stop_is_valid; 395 }; 396 397 398 399 //---------------------------------------------------------------------- 400 // StopInfoUnixSignal 401 //---------------------------------------------------------------------- 402 403 class StopInfoUnixSignal : public StopInfo 404 { 405 public: 406 407 StopInfoUnixSignal (Thread &thread, int signo) : 408 StopInfo (thread, signo) 409 { 410 } 411 412 virtual ~StopInfoUnixSignal () 413 { 414 } 415 416 417 virtual StopReason 418 GetStopReason () const 419 { 420 return eStopReasonSignal; 421 } 422 423 virtual bool 424 ShouldStop (Event *event_ptr) 425 { 426 return m_thread.GetProcess().GetUnixSignals().GetShouldStop (m_value); 427 } 428 429 430 // If should stop returns false, check if we should notify of this event 431 virtual bool 432 ShouldNotify (Event *event_ptr) 433 { 434 return m_thread.GetProcess().GetUnixSignals().GetShouldNotify (m_value); 435 } 436 437 438 virtual void 439 WillResume (lldb::StateType resume_state) 440 { 441 if (m_thread.GetProcess().GetUnixSignals().GetShouldSuppress(m_value) == false) 442 m_thread.SetResumeSignal(m_value); 443 } 444 445 virtual const char * 446 GetDescription () 447 { 448 if (m_description.empty()) 449 { 450 StreamString strm; 451 const char *signal_name = m_thread.GetProcess().GetUnixSignals().GetSignalAsCString (m_value); 452 if (signal_name) 453 strm.Printf("signal %s", signal_name); 454 else 455 strm.Printf("signal %lli", m_value); 456 m_description.swap (strm.GetString()); 457 } 458 return m_description.c_str(); 459 } 460 }; 461 462 //---------------------------------------------------------------------- 463 // StopInfoTrace 464 //---------------------------------------------------------------------- 465 466 class StopInfoTrace : public StopInfo 467 { 468 public: 469 470 StopInfoTrace (Thread &thread) : 471 StopInfo (thread, LLDB_INVALID_UID) 472 { 473 } 474 475 virtual ~StopInfoTrace () 476 { 477 } 478 479 virtual StopReason 480 GetStopReason () const 481 { 482 return eStopReasonTrace; 483 } 484 485 virtual const char * 486 GetDescription () 487 { 488 if (m_description.empty()) 489 return "trace"; 490 else 491 return m_description.c_str(); 492 } 493 }; 494 495 496 //---------------------------------------------------------------------- 497 // StopInfoException 498 //---------------------------------------------------------------------- 499 500 class StopInfoException : public StopInfo 501 { 502 public: 503 504 StopInfoException (Thread &thread, const char *description) : 505 StopInfo (thread, LLDB_INVALID_UID) 506 { 507 if (description) 508 SetDescription (description); 509 } 510 511 virtual 512 ~StopInfoException () 513 { 514 } 515 516 virtual StopReason 517 GetStopReason () const 518 { 519 return eStopReasonException; 520 } 521 522 virtual const char * 523 GetDescription () 524 { 525 if (m_description.empty()) 526 return "exception"; 527 else 528 return m_description.c_str(); 529 } 530 }; 531 532 533 //---------------------------------------------------------------------- 534 // StopInfoThreadPlan 535 //---------------------------------------------------------------------- 536 537 class StopInfoThreadPlan : public StopInfo 538 { 539 public: 540 541 StopInfoThreadPlan (ThreadPlanSP &plan_sp) : 542 StopInfo (plan_sp->GetThread(), LLDB_INVALID_UID), 543 m_plan_sp (plan_sp) 544 { 545 } 546 547 virtual ~StopInfoThreadPlan () 548 { 549 } 550 551 virtual StopReason 552 GetStopReason () const 553 { 554 return eStopReasonPlanComplete; 555 } 556 557 virtual const char * 558 GetDescription () 559 { 560 if (m_description.empty()) 561 { 562 StreamString strm; 563 m_plan_sp->GetDescription (&strm, eDescriptionLevelBrief); 564 m_description.swap (strm.GetString()); 565 } 566 return m_description.c_str(); 567 } 568 569 private: 570 ThreadPlanSP m_plan_sp; 571 }; 572 } // namespace lldb_private 573 574 StopInfoSP 575 StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id) 576 { 577 return StopInfoSP (new StopInfoBreakpoint (thread, break_id)); 578 } 579 580 StopInfoSP 581 StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id, bool should_stop) 582 { 583 return StopInfoSP (new StopInfoBreakpoint (thread, break_id, should_stop)); 584 } 585 586 StopInfoSP 587 StopInfo::CreateStopReasonWithWatchpointID (Thread &thread, break_id_t watch_id) 588 { 589 return StopInfoSP (new StopInfoWatchpoint (thread, watch_id)); 590 } 591 592 StopInfoSP 593 StopInfo::CreateStopReasonWithSignal (Thread &thread, int signo) 594 { 595 return StopInfoSP (new StopInfoUnixSignal (thread, signo)); 596 } 597 598 StopInfoSP 599 StopInfo::CreateStopReasonToTrace (Thread &thread) 600 { 601 return StopInfoSP (new StopInfoTrace (thread)); 602 } 603 604 StopInfoSP 605 StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp) 606 { 607 return StopInfoSP (new StopInfoThreadPlan (plan_sp)); 608 } 609 610 StopInfoSP 611 StopInfo::CreateStopReasonWithException (Thread &thread, const char *description) 612 { 613 return StopInfoSP (new StopInfoException (thread, description)); 614 } 615