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