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