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