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 eExecutionPolicyAlways, 198 discard_on_error, 199 bp_loc_sp->GetConditionText(), 200 NULL, 201 result_value_sp, 202 error); 203 if (result_code == eExecutionCompleted) 204 { 205 if (result_value_sp) 206 { 207 Scalar scalar_value; 208 if (result_value_sp->ResolveValue (scalar_value)) 209 { 210 if (scalar_value.ULongLong(1) == 0) 211 m_should_stop = false; 212 else 213 m_should_stop = true; 214 if (log) 215 log->Printf("Condition successfully evaluated, result is %s.\n", 216 m_should_stop ? "true" : "false"); 217 } 218 else 219 { 220 m_should_stop = true; 221 if (log) 222 log->Printf("Failed to get an integer result from the expression."); 223 } 224 } 225 } 226 else 227 { 228 Debugger &debugger = context.exe_ctx.target->GetDebugger(); 229 StreamSP error_sp = debugger.GetAsyncErrorStream (); 230 error_sp->Printf ("Stopped due to an error evaluating condition of breakpoint "); 231 bp_loc_sp->GetDescription (error_sp.get(), eDescriptionLevelBrief); 232 error_sp->Printf (": \"%s\"", 233 bp_loc_sp->GetConditionText()); 234 error_sp->EOL(); 235 const char *err_str = error.AsCString("<Unknown Error>"); 236 if (log) 237 log->Printf("Error evaluating condition: \"%s\"\n", err_str); 238 239 error_sp->PutCString (err_str); 240 error_sp->EOL(); 241 error_sp->Flush(); 242 // If the condition fails to be parsed or run, we should stop. 243 m_should_stop = true; 244 } 245 } 246 247 // If any condition says we should stop, then we're going to stop, so we don't need 248 // to evaluate the others. 249 if (m_should_stop) 250 break; 251 } 252 } 253 } 254 else 255 { 256 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 257 258 if (log) 259 log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value); 260 } 261 if (log) 262 log->Printf ("Process::%s returning from action with m_should_stop: %d.", __FUNCTION__, m_should_stop); 263 } 264 265 virtual bool 266 ShouldNotify (Event *event_ptr) 267 { 268 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 269 if (bp_site_sp) 270 { 271 bool all_internal = true; 272 273 for (uint32_t i = 0; i < bp_site_sp->GetNumberOfOwners(); i++) 274 { 275 if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) 276 { 277 all_internal = false; 278 break; 279 } 280 } 281 return all_internal == false; 282 } 283 return true; 284 } 285 286 virtual const char * 287 GetDescription () 288 { 289 if (m_description.empty()) 290 { 291 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 292 if (bp_site_sp) 293 { 294 StreamString strm; 295 strm.Printf("breakpoint "); 296 bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief); 297 m_description.swap (strm.GetString()); 298 } 299 else 300 { 301 StreamString strm; 302 strm.Printf("breakpoint site %lli", m_value); 303 m_description.swap (strm.GetString()); 304 } 305 } 306 return m_description.c_str(); 307 } 308 309 private: 310 std::string m_description; 311 bool m_should_stop; 312 bool m_should_stop_is_valid; 313 bool m_should_perform_action; // Since we are trying to preserve the "state" of the system even if we run functions 314 // etc. behind the users backs, we need to make sure we only REALLY perform the action once. 315 }; 316 317 318 //---------------------------------------------------------------------- 319 // StopInfoWatchpoint 320 //---------------------------------------------------------------------- 321 322 class StopInfoWatchpoint : public StopInfo 323 { 324 public: 325 326 StopInfoWatchpoint (Thread &thread, break_id_t watch_id) : 327 StopInfo (thread, watch_id), 328 m_description() 329 { 330 } 331 332 virtual ~StopInfoWatchpoint () 333 { 334 } 335 336 virtual StopReason 337 GetStopReason () const 338 { 339 return eStopReasonWatchpoint; 340 } 341 342 virtual const char * 343 GetDescription () 344 { 345 if (m_description.empty()) 346 { 347 StreamString strm; 348 strm.Printf("watchpoint %lli", m_value); 349 m_description.swap (strm.GetString()); 350 } 351 return m_description.c_str(); 352 } 353 354 355 356 private: 357 std::string m_description; 358 }; 359 360 361 362 //---------------------------------------------------------------------- 363 // StopInfoUnixSignal 364 //---------------------------------------------------------------------- 365 366 class StopInfoUnixSignal : public StopInfo 367 { 368 public: 369 370 StopInfoUnixSignal (Thread &thread, int signo) : 371 StopInfo (thread, signo) 372 { 373 } 374 375 virtual ~StopInfoUnixSignal () 376 { 377 } 378 379 380 virtual StopReason 381 GetStopReason () const 382 { 383 return eStopReasonSignal; 384 } 385 386 virtual bool 387 ShouldStop (Event *event_ptr) 388 { 389 return m_thread.GetProcess().GetUnixSignals().GetShouldStop (m_value); 390 } 391 392 393 // If should stop returns false, check if we should notify of this event 394 virtual bool 395 ShouldNotify (Event *event_ptr) 396 { 397 return m_thread.GetProcess().GetUnixSignals().GetShouldNotify (m_value); 398 } 399 400 401 virtual void 402 WillResume (lldb::StateType resume_state) 403 { 404 if (m_thread.GetProcess().GetUnixSignals().GetShouldSuppress(m_value) == false) 405 m_thread.SetResumeSignal(m_value); 406 } 407 408 virtual const char * 409 GetDescription () 410 { 411 if (m_description.empty()) 412 { 413 StreamString strm; 414 const char *signal_name = m_thread.GetProcess().GetUnixSignals().GetSignalAsCString (m_value); 415 if (signal_name) 416 strm.Printf("signal %s", signal_name); 417 else 418 strm.Printf("signal %lli", m_value); 419 m_description.swap (strm.GetString()); 420 } 421 return m_description.c_str(); 422 } 423 }; 424 425 //---------------------------------------------------------------------- 426 // StopInfoTrace 427 //---------------------------------------------------------------------- 428 429 class StopInfoTrace : public StopInfo 430 { 431 public: 432 433 StopInfoTrace (Thread &thread) : 434 StopInfo (thread, LLDB_INVALID_UID) 435 { 436 } 437 438 virtual ~StopInfoTrace () 439 { 440 } 441 442 virtual StopReason 443 GetStopReason () const 444 { 445 return eStopReasonTrace; 446 } 447 448 virtual const char * 449 GetDescription () 450 { 451 if (m_description.empty()) 452 return "trace"; 453 else 454 return m_description.c_str(); 455 } 456 }; 457 458 459 //---------------------------------------------------------------------- 460 // StopInfoException 461 //---------------------------------------------------------------------- 462 463 class StopInfoException : public StopInfo 464 { 465 public: 466 467 StopInfoException (Thread &thread, const char *description) : 468 StopInfo (thread, LLDB_INVALID_UID) 469 { 470 if (description) 471 SetDescription (description); 472 } 473 474 virtual 475 ~StopInfoException () 476 { 477 } 478 479 virtual StopReason 480 GetStopReason () const 481 { 482 return eStopReasonException; 483 } 484 485 virtual const char * 486 GetDescription () 487 { 488 if (m_description.empty()) 489 return "exception"; 490 else 491 return m_description.c_str(); 492 } 493 }; 494 495 496 //---------------------------------------------------------------------- 497 // StopInfoThreadPlan 498 //---------------------------------------------------------------------- 499 500 class StopInfoThreadPlan : public StopInfo 501 { 502 public: 503 504 StopInfoThreadPlan (ThreadPlanSP &plan_sp) : 505 StopInfo (plan_sp->GetThread(), LLDB_INVALID_UID), 506 m_plan_sp (plan_sp) 507 { 508 } 509 510 virtual ~StopInfoThreadPlan () 511 { 512 } 513 514 virtual StopReason 515 GetStopReason () const 516 { 517 return eStopReasonPlanComplete; 518 } 519 520 virtual const char * 521 GetDescription () 522 { 523 if (m_description.empty()) 524 { 525 StreamString strm; 526 m_plan_sp->GetDescription (&strm, eDescriptionLevelBrief); 527 m_description.swap (strm.GetString()); 528 } 529 return m_description.c_str(); 530 } 531 532 private: 533 ThreadPlanSP m_plan_sp; 534 }; 535 } // namespace lldb_private 536 537 StopInfoSP 538 StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id) 539 { 540 return StopInfoSP (new StopInfoBreakpoint (thread, break_id)); 541 } 542 543 StopInfoSP 544 StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id, bool should_stop) 545 { 546 return StopInfoSP (new StopInfoBreakpoint (thread, break_id, should_stop)); 547 } 548 549 StopInfoSP 550 StopInfo::CreateStopReasonWithWatchpointID (Thread &thread, break_id_t watch_id) 551 { 552 return StopInfoSP (new StopInfoWatchpoint (thread, watch_id)); 553 } 554 555 StopInfoSP 556 StopInfo::CreateStopReasonWithSignal (Thread &thread, int signo) 557 { 558 return StopInfoSP (new StopInfoUnixSignal (thread, signo)); 559 } 560 561 StopInfoSP 562 StopInfo::CreateStopReasonToTrace (Thread &thread) 563 { 564 return StopInfoSP (new StopInfoTrace (thread)); 565 } 566 567 StopInfoSP 568 StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp) 569 { 570 return StopInfoSP (new StopInfoThreadPlan (plan_sp)); 571 } 572 573 StopInfoSP 574 StopInfo::CreateStopReasonWithException (Thread &thread, const char *description) 575 { 576 return StopInfoSP (new StopInfoException (thread, description)); 577 } 578