1 //===-- SBBreakpoint.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/API/SBBreakpoint.h" 11 #include "lldb/API/SBBreakpointLocation.h" 12 #include "lldb/API/SBDebugger.h" 13 #include "lldb/API/SBEvent.h" 14 #include "lldb/API/SBProcess.h" 15 #include "lldb/API/SBStream.h" 16 #include "lldb/API/SBThread.h" 17 18 #include "lldb/Breakpoint/Breakpoint.h" 19 #include "lldb/Breakpoint/BreakpointLocation.h" 20 #include "lldb/Breakpoint/StoppointCallbackContext.h" 21 #include "lldb/Core/Address.h" 22 #include "lldb/Core/Log.h" 23 #include "lldb/Core/Stream.h" 24 #include "lldb/Core/StreamFile.h" 25 #include "lldb/Target/Process.h" 26 #include "lldb/Target/Target.h" 27 #include "lldb/Target/Thread.h" 28 #include "lldb/Target/ThreadSpec.h" 29 30 31 #include "lldb/lldb-enumerations.h" 32 33 using namespace lldb; 34 using namespace lldb_private; 35 36 struct CallbackData 37 { 38 SBBreakpoint::BreakpointHitCallback callback; 39 void *callback_baton; 40 }; 41 42 class SBBreakpointCallbackBaton : public Baton 43 { 44 public: 45 46 SBBreakpointCallbackBaton (SBBreakpoint::BreakpointHitCallback callback, void *baton) : 47 Baton (new CallbackData) 48 { 49 CallbackData *data = (CallbackData *)m_data; 50 data->callback = callback; 51 data->callback_baton = baton; 52 } 53 54 virtual ~SBBreakpointCallbackBaton() 55 { 56 CallbackData *data = (CallbackData *)m_data; 57 58 if (data) 59 { 60 delete data; 61 m_data = NULL; 62 } 63 } 64 }; 65 66 67 SBBreakpoint::SBBreakpoint () : 68 m_opaque_sp () 69 { 70 } 71 72 SBBreakpoint::SBBreakpoint (const SBBreakpoint& rhs) : 73 m_opaque_sp (rhs.m_opaque_sp) 74 { 75 } 76 77 78 SBBreakpoint::SBBreakpoint (const lldb::BreakpointSP &bp_sp) : 79 m_opaque_sp (bp_sp) 80 { 81 } 82 83 SBBreakpoint::~SBBreakpoint() 84 { 85 } 86 87 const SBBreakpoint & 88 SBBreakpoint::operator = (const SBBreakpoint& rhs) 89 { 90 if (this != &rhs) 91 m_opaque_sp = rhs.m_opaque_sp; 92 return *this; 93 } 94 95 bool 96 SBBreakpoint::operator == (const lldb::SBBreakpoint& rhs) 97 { 98 if (m_opaque_sp && rhs.m_opaque_sp) 99 return m_opaque_sp.get() == rhs.m_opaque_sp.get(); 100 return false; 101 } 102 103 bool 104 SBBreakpoint::operator != (const lldb::SBBreakpoint& rhs) 105 { 106 if (m_opaque_sp && rhs.m_opaque_sp) 107 return m_opaque_sp.get() != rhs.m_opaque_sp.get(); 108 return (m_opaque_sp && !rhs.m_opaque_sp) || (rhs.m_opaque_sp && !m_opaque_sp); 109 } 110 111 break_id_t 112 SBBreakpoint::GetID () const 113 { 114 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 115 116 break_id_t break_id = LLDB_INVALID_BREAK_ID; 117 if (m_opaque_sp) 118 break_id = m_opaque_sp->GetID(); 119 120 if (log) 121 { 122 if (break_id == LLDB_INVALID_BREAK_ID) 123 log->Printf ("SBBreakpoint(%p)::GetID () => LLDB_INVALID_BREAK_ID", m_opaque_sp.get()); 124 else 125 log->Printf ("SBBreakpoint(%p)::GetID () => %u", m_opaque_sp.get(), break_id); 126 } 127 128 return break_id; 129 } 130 131 132 bool 133 SBBreakpoint::IsValid() const 134 { 135 return (bool) m_opaque_sp; 136 } 137 138 void 139 SBBreakpoint::ClearAllBreakpointSites () 140 { 141 if (m_opaque_sp) 142 { 143 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 144 m_opaque_sp->ClearAllBreakpointSites (); 145 } 146 } 147 148 SBBreakpointLocation 149 SBBreakpoint::FindLocationByAddress (addr_t vm_addr) 150 { 151 SBBreakpointLocation sb_bp_location; 152 153 if (m_opaque_sp) 154 { 155 if (vm_addr != LLDB_INVALID_ADDRESS) 156 { 157 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 158 Address address; 159 Target &target = m_opaque_sp->GetTarget(); 160 if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false) 161 { 162 address.SetRawAddress (vm_addr); 163 } 164 sb_bp_location.SetLocation (m_opaque_sp->FindLocationByAddress (address)); 165 } 166 } 167 return sb_bp_location; 168 } 169 170 break_id_t 171 SBBreakpoint::FindLocationIDByAddress (addr_t vm_addr) 172 { 173 break_id_t break_id = LLDB_INVALID_BREAK_ID; 174 175 if (m_opaque_sp && vm_addr != LLDB_INVALID_ADDRESS) 176 { 177 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 178 Address address; 179 Target &target = m_opaque_sp->GetTarget(); 180 if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false) 181 { 182 address.SetRawAddress (vm_addr); 183 } 184 break_id = m_opaque_sp->FindLocationIDByAddress (address); 185 } 186 187 return break_id; 188 } 189 190 SBBreakpointLocation 191 SBBreakpoint::FindLocationByID (break_id_t bp_loc_id) 192 { 193 SBBreakpointLocation sb_bp_location; 194 195 if (m_opaque_sp) 196 { 197 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 198 sb_bp_location.SetLocation (m_opaque_sp->FindLocationByID (bp_loc_id)); 199 } 200 201 return sb_bp_location; 202 } 203 204 SBBreakpointLocation 205 SBBreakpoint::GetLocationAtIndex (uint32_t index) 206 { 207 SBBreakpointLocation sb_bp_location; 208 209 if (m_opaque_sp) 210 { 211 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 212 sb_bp_location.SetLocation (m_opaque_sp->GetLocationAtIndex (index)); 213 } 214 215 return sb_bp_location; 216 } 217 218 void 219 SBBreakpoint::SetEnabled (bool enable) 220 { 221 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 222 223 if (log) 224 log->Printf ("SBBreakpoint(%p)::SetEnabled (enabled=%i)", m_opaque_sp.get(), enable); 225 226 if (m_opaque_sp) 227 { 228 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 229 m_opaque_sp->SetEnabled (enable); 230 } 231 } 232 233 bool 234 SBBreakpoint::IsEnabled () 235 { 236 if (m_opaque_sp) 237 { 238 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 239 return m_opaque_sp->IsEnabled(); 240 } 241 else 242 return false; 243 } 244 245 void 246 SBBreakpoint::SetOneShot (bool one_shot) 247 { 248 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 249 250 if (log) 251 log->Printf ("SBBreakpoint(%p)::SetOneShot (one_shot=%i)", m_opaque_sp.get(), one_shot); 252 253 if (m_opaque_sp) 254 { 255 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 256 m_opaque_sp->SetOneShot (one_shot); 257 } 258 } 259 260 bool 261 SBBreakpoint::IsOneShot () const 262 { 263 if (m_opaque_sp) 264 { 265 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 266 return m_opaque_sp->IsOneShot(); 267 } 268 else 269 return false; 270 } 271 272 bool 273 SBBreakpoint::IsInternal () 274 { 275 if (m_opaque_sp) 276 { 277 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 278 return m_opaque_sp->IsInternal(); 279 } 280 else 281 return false; 282 } 283 284 void 285 SBBreakpoint::SetIgnoreCount (uint32_t count) 286 { 287 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 288 289 if (log) 290 log->Printf ("SBBreakpoint(%p)::SetIgnoreCount (count=%u)", m_opaque_sp.get(), count); 291 292 if (m_opaque_sp) 293 { 294 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 295 m_opaque_sp->SetIgnoreCount (count); 296 } 297 } 298 299 void 300 SBBreakpoint::SetCondition (const char *condition) 301 { 302 if (m_opaque_sp) 303 { 304 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 305 m_opaque_sp->SetCondition (condition); 306 } 307 } 308 309 const char * 310 SBBreakpoint::GetCondition () 311 { 312 if (m_opaque_sp) 313 { 314 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 315 return m_opaque_sp->GetConditionText (); 316 } 317 return NULL; 318 } 319 320 uint32_t 321 SBBreakpoint::GetHitCount () const 322 { 323 uint32_t count = 0; 324 if (m_opaque_sp) 325 { 326 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 327 count = m_opaque_sp->GetHitCount(); 328 } 329 330 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 331 if (log) 332 log->Printf ("SBBreakpoint(%p)::GetHitCount () => %u", m_opaque_sp.get(), count); 333 334 return count; 335 } 336 337 uint32_t 338 SBBreakpoint::GetIgnoreCount () const 339 { 340 uint32_t count = 0; 341 if (m_opaque_sp) 342 { 343 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 344 count = m_opaque_sp->GetIgnoreCount(); 345 } 346 347 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 348 if (log) 349 log->Printf ("SBBreakpoint(%p)::GetIgnoreCount () => %u", m_opaque_sp.get(), count); 350 351 return count; 352 } 353 354 void 355 SBBreakpoint::SetThreadID (tid_t tid) 356 { 357 if (m_opaque_sp) 358 { 359 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 360 m_opaque_sp->SetThreadID (tid); 361 } 362 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 363 if (log) 364 log->Printf ("SBBreakpoint(%p)::SetThreadID (tid=0x%4.4" PRIx64 ")", m_opaque_sp.get(), tid); 365 366 } 367 368 tid_t 369 SBBreakpoint::GetThreadID () 370 { 371 tid_t tid = LLDB_INVALID_THREAD_ID; 372 if (m_opaque_sp) 373 { 374 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 375 tid = m_opaque_sp->GetThreadID(); 376 } 377 378 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 379 if (log) 380 log->Printf ("SBBreakpoint(%p)::GetThreadID () => 0x%4.4" PRIx64, m_opaque_sp.get(), tid); 381 return tid; 382 } 383 384 void 385 SBBreakpoint::SetThreadIndex (uint32_t index) 386 { 387 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 388 if (log) 389 log->Printf ("SBBreakpoint(%p)::SetThreadIndex (%u)", m_opaque_sp.get(), index); 390 if (m_opaque_sp) 391 { 392 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 393 m_opaque_sp->GetOptions()->GetThreadSpec()->SetIndex (index); 394 } 395 } 396 397 uint32_t 398 SBBreakpoint::GetThreadIndex() const 399 { 400 uint32_t thread_idx = UINT32_MAX; 401 if (m_opaque_sp) 402 { 403 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 404 const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate(); 405 if (thread_spec != NULL) 406 thread_idx = thread_spec->GetIndex(); 407 } 408 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 409 if (log) 410 log->Printf ("SBBreakpoint(%p)::GetThreadIndex () => %u", m_opaque_sp.get(), thread_idx); 411 412 return thread_idx; 413 } 414 415 416 void 417 SBBreakpoint::SetThreadName (const char *thread_name) 418 { 419 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 420 if (log) 421 log->Printf ("SBBreakpoint(%p)::SetThreadName (%s)", m_opaque_sp.get(), thread_name); 422 423 if (m_opaque_sp) 424 { 425 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 426 m_opaque_sp->GetOptions()->GetThreadSpec()->SetName (thread_name); 427 } 428 } 429 430 const char * 431 SBBreakpoint::GetThreadName () const 432 { 433 const char *name = NULL; 434 if (m_opaque_sp) 435 { 436 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 437 const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate(); 438 if (thread_spec != NULL) 439 name = thread_spec->GetName(); 440 } 441 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 442 if (log) 443 log->Printf ("SBBreakpoint(%p)::GetThreadName () => %s", m_opaque_sp.get(), name); 444 445 return name; 446 } 447 448 void 449 SBBreakpoint::SetQueueName (const char *queue_name) 450 { 451 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 452 if (log) 453 log->Printf ("SBBreakpoint(%p)::SetQueueName (%s)", m_opaque_sp.get(), queue_name); 454 if (m_opaque_sp) 455 { 456 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 457 m_opaque_sp->GetOptions()->GetThreadSpec()->SetQueueName (queue_name); 458 } 459 } 460 461 const char * 462 SBBreakpoint::GetQueueName () const 463 { 464 const char *name = NULL; 465 if (m_opaque_sp) 466 { 467 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 468 const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate(); 469 if (thread_spec) 470 name = thread_spec->GetQueueName(); 471 } 472 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 473 if (log) 474 log->Printf ("SBBreakpoint(%p)::GetQueueName () => %s", m_opaque_sp.get(), name); 475 476 return name; 477 } 478 479 size_t 480 SBBreakpoint::GetNumResolvedLocations() const 481 { 482 size_t num_resolved = 0; 483 if (m_opaque_sp) 484 { 485 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 486 num_resolved = m_opaque_sp->GetNumResolvedLocations(); 487 } 488 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 489 if (log) 490 log->Printf ("SBBreakpoint(%p)::GetNumResolvedLocations () => %" PRIu64, m_opaque_sp.get(), (uint64_t)num_resolved); 491 return num_resolved; 492 } 493 494 size_t 495 SBBreakpoint::GetNumLocations() const 496 { 497 size_t num_locs = 0; 498 if (m_opaque_sp) 499 { 500 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 501 num_locs = m_opaque_sp->GetNumLocations(); 502 } 503 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 504 if (log) 505 log->Printf ("SBBreakpoint(%p)::GetNumLocations () => %" PRIu64, m_opaque_sp.get(), (uint64_t)num_locs); 506 return num_locs; 507 } 508 509 bool 510 SBBreakpoint::GetDescription (SBStream &s) 511 { 512 if (m_opaque_sp) 513 { 514 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 515 s.Printf("SBBreakpoint: id = %i, ", m_opaque_sp->GetID()); 516 m_opaque_sp->GetResolverDescription (s.get()); 517 m_opaque_sp->GetFilterDescription (s.get()); 518 const size_t num_locations = m_opaque_sp->GetNumLocations (); 519 s.Printf(", locations = %" PRIu64, (uint64_t)num_locations); 520 return true; 521 } 522 s.Printf ("No value"); 523 return false; 524 } 525 526 bool 527 SBBreakpoint::PrivateBreakpointHitCallback 528 ( 529 void *baton, 530 StoppointCallbackContext *ctx, 531 lldb::user_id_t break_id, 532 lldb::user_id_t break_loc_id 533 ) 534 { 535 ExecutionContext exe_ctx (ctx->exe_ctx_ref); 536 BreakpointSP bp_sp(exe_ctx.GetTargetRef().GetBreakpointList().FindBreakpointByID(break_id)); 537 if (baton && bp_sp) 538 { 539 CallbackData *data = (CallbackData *)baton; 540 lldb_private::Breakpoint *bp = bp_sp.get(); 541 if (bp && data->callback) 542 { 543 Process *process = exe_ctx.GetProcessPtr(); 544 if (process) 545 { 546 SBProcess sb_process (process->shared_from_this()); 547 SBThread sb_thread; 548 SBBreakpointLocation sb_location; 549 assert (bp_sp); 550 sb_location.SetLocation (bp_sp->FindLocationByID (break_loc_id)); 551 Thread *thread = exe_ctx.GetThreadPtr(); 552 if (thread) 553 sb_thread.SetThread(thread->shared_from_this()); 554 555 return data->callback (data->callback_baton, 556 sb_process, 557 sb_thread, 558 sb_location); 559 } 560 } 561 } 562 return true; // Return true if we should stop at this breakpoint 563 } 564 565 void 566 SBBreakpoint::SetCallback (BreakpointHitCallback callback, void *baton) 567 { 568 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 569 570 if (log) 571 log->Printf ("SBBreakpoint(%p)::SetCallback (callback=%p, baton=%p)", m_opaque_sp.get(), callback, baton); 572 573 if (m_opaque_sp) 574 { 575 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 576 BatonSP baton_sp(new SBBreakpointCallbackBaton (callback, baton)); 577 m_opaque_sp->SetCallback (SBBreakpoint::PrivateBreakpointHitCallback, baton_sp, false); 578 } 579 } 580 581 582 lldb_private::Breakpoint * 583 SBBreakpoint::operator->() const 584 { 585 return m_opaque_sp.get(); 586 } 587 588 lldb_private::Breakpoint * 589 SBBreakpoint::get() const 590 { 591 return m_opaque_sp.get(); 592 } 593 594 lldb::BreakpointSP & 595 SBBreakpoint::operator *() 596 { 597 return m_opaque_sp; 598 } 599 600 const lldb::BreakpointSP & 601 SBBreakpoint::operator *() const 602 { 603 return m_opaque_sp; 604 } 605 606 bool 607 SBBreakpoint::EventIsBreakpointEvent (const lldb::SBEvent &event) 608 { 609 return Breakpoint::BreakpointEventData::GetEventDataFromEvent(event.get()) != NULL; 610 611 } 612 613 BreakpointEventType 614 SBBreakpoint::GetBreakpointEventTypeFromEvent (const SBEvent& event) 615 { 616 if (event.IsValid()) 617 return Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event.GetSP()); 618 return eBreakpointEventTypeInvalidType; 619 } 620 621 SBBreakpoint 622 SBBreakpoint::GetBreakpointFromEvent (const lldb::SBEvent& event) 623 { 624 SBBreakpoint sb_breakpoint; 625 if (event.IsValid()) 626 sb_breakpoint.m_opaque_sp = Breakpoint::BreakpointEventData::GetBreakpointFromEvent (event.GetSP()); 627 return sb_breakpoint; 628 } 629 630 SBBreakpointLocation 631 SBBreakpoint::GetBreakpointLocationAtIndexFromEvent (const lldb::SBEvent& event, uint32_t loc_idx) 632 { 633 SBBreakpointLocation sb_breakpoint_loc; 634 if (event.IsValid()) 635 sb_breakpoint_loc.SetLocation (Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent (event.GetSP(), loc_idx)); 636 return sb_breakpoint_loc; 637 } 638 639 uint32_t 640 SBBreakpoint::GetNumBreakpointLocationsFromEvent (const lldb::SBEvent &event) 641 { 642 uint32_t num_locations = 0; 643 if (event.IsValid()) 644 num_locations = (Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent (event.GetSP())); 645 return num_locations; 646 } 647 648 649