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 bool 238 SBBreakpoint::IsInternal () 239 { 240 if (m_opaque_sp) 241 { 242 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 243 return m_opaque_sp->IsInternal(); 244 } 245 else 246 return false; 247 } 248 249 void 250 SBBreakpoint::SetIgnoreCount (uint32_t count) 251 { 252 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 253 254 if (log) 255 log->Printf ("SBBreakpoint(%p)::SetIgnoreCount (count=%u)", m_opaque_sp.get(), count); 256 257 if (m_opaque_sp) 258 { 259 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 260 m_opaque_sp->SetIgnoreCount (count); 261 } 262 } 263 264 void 265 SBBreakpoint::SetCondition (const char *condition) 266 { 267 if (m_opaque_sp) 268 { 269 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 270 m_opaque_sp->SetCondition (condition); 271 } 272 } 273 274 const char * 275 SBBreakpoint::GetCondition () 276 { 277 if (m_opaque_sp) 278 { 279 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 280 return m_opaque_sp->GetConditionText (); 281 } 282 return NULL; 283 } 284 285 uint32_t 286 SBBreakpoint::GetHitCount () const 287 { 288 uint32_t count = 0; 289 if (m_opaque_sp) 290 { 291 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 292 count = m_opaque_sp->GetHitCount(); 293 } 294 295 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 296 if (log) 297 log->Printf ("SBBreakpoint(%p)::GetHitCount () => %u", m_opaque_sp.get(), count); 298 299 return count; 300 } 301 302 uint32_t 303 SBBreakpoint::GetIgnoreCount () const 304 { 305 uint32_t count = 0; 306 if (m_opaque_sp) 307 { 308 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 309 count = m_opaque_sp->GetIgnoreCount(); 310 } 311 312 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 313 if (log) 314 log->Printf ("SBBreakpoint(%p)::GetIgnoreCount () => %u", m_opaque_sp.get(), count); 315 316 return count; 317 } 318 319 void 320 SBBreakpoint::SetThreadID (tid_t tid) 321 { 322 if (m_opaque_sp) 323 { 324 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 325 m_opaque_sp->SetThreadID (tid); 326 } 327 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 328 if (log) 329 log->Printf ("SBBreakpoint(%p)::SetThreadID (tid=0x%4.4llx)", m_opaque_sp.get(), tid); 330 331 } 332 333 tid_t 334 SBBreakpoint::GetThreadID () 335 { 336 tid_t tid = LLDB_INVALID_THREAD_ID; 337 if (m_opaque_sp) 338 { 339 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 340 tid = m_opaque_sp->GetThreadID(); 341 } 342 343 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 344 if (log) 345 log->Printf ("SBBreakpoint(%p)::GetThreadID () => 0x%4.4llx", m_opaque_sp.get(), tid); 346 return tid; 347 } 348 349 void 350 SBBreakpoint::SetThreadIndex (uint32_t index) 351 { 352 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 353 if (log) 354 log->Printf ("SBBreakpoint(%p)::SetThreadIndex (%u)", m_opaque_sp.get(), index); 355 if (m_opaque_sp) 356 { 357 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 358 m_opaque_sp->GetOptions()->GetThreadSpec()->SetIndex (index); 359 } 360 } 361 362 uint32_t 363 SBBreakpoint::GetThreadIndex() const 364 { 365 uint32_t thread_idx = UINT32_MAX; 366 if (m_opaque_sp) 367 { 368 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 369 const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate(); 370 if (thread_spec != NULL) 371 thread_idx = thread_spec->GetIndex(); 372 } 373 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 374 if (log) 375 log->Printf ("SBBreakpoint(%p)::GetThreadIndex () => %u", m_opaque_sp.get(), thread_idx); 376 377 return thread_idx; 378 } 379 380 381 void 382 SBBreakpoint::SetThreadName (const char *thread_name) 383 { 384 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 385 if (log) 386 log->Printf ("SBBreakpoint(%p)::SetThreadName (%s)", m_opaque_sp.get(), thread_name); 387 388 if (m_opaque_sp) 389 { 390 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 391 m_opaque_sp->GetOptions()->GetThreadSpec()->SetName (thread_name); 392 } 393 } 394 395 const char * 396 SBBreakpoint::GetThreadName () const 397 { 398 const char *name = NULL; 399 if (m_opaque_sp) 400 { 401 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 402 const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate(); 403 if (thread_spec != NULL) 404 name = thread_spec->GetName(); 405 } 406 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 407 if (log) 408 log->Printf ("SBBreakpoint(%p)::GetThreadName () => %s", m_opaque_sp.get(), name); 409 410 return name; 411 } 412 413 void 414 SBBreakpoint::SetQueueName (const char *queue_name) 415 { 416 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 417 if (log) 418 log->Printf ("SBBreakpoint(%p)::SetQueueName (%s)", m_opaque_sp.get(), queue_name); 419 if (m_opaque_sp) 420 { 421 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 422 m_opaque_sp->GetOptions()->GetThreadSpec()->SetQueueName (queue_name); 423 } 424 } 425 426 const char * 427 SBBreakpoint::GetQueueName () const 428 { 429 const char *name = NULL; 430 if (m_opaque_sp) 431 { 432 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 433 const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate(); 434 if (thread_spec) 435 name = thread_spec->GetQueueName(); 436 } 437 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 438 if (log) 439 log->Printf ("SBBreakpoint(%p)::GetQueueName () => %s", m_opaque_sp.get(), name); 440 441 return name; 442 } 443 444 size_t 445 SBBreakpoint::GetNumResolvedLocations() const 446 { 447 size_t num_resolved = 0; 448 if (m_opaque_sp) 449 { 450 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 451 num_resolved = m_opaque_sp->GetNumResolvedLocations(); 452 } 453 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 454 if (log) 455 log->Printf ("SBBreakpoint(%p)::GetNumResolvedLocations () => %llu", m_opaque_sp.get(), (uint64_t)num_resolved); 456 return num_resolved; 457 } 458 459 size_t 460 SBBreakpoint::GetNumLocations() const 461 { 462 size_t num_locs = 0; 463 if (m_opaque_sp) 464 { 465 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 466 num_locs = m_opaque_sp->GetNumLocations(); 467 } 468 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 469 if (log) 470 log->Printf ("SBBreakpoint(%p)::GetNumLocations () => %llu", m_opaque_sp.get(), (uint64_t)num_locs); 471 return num_locs; 472 } 473 474 bool 475 SBBreakpoint::GetDescription (SBStream &s) 476 { 477 if (m_opaque_sp) 478 { 479 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 480 s.Printf("SBBreakpoint: id = %i, ", m_opaque_sp->GetID()); 481 m_opaque_sp->GetResolverDescription (s.get()); 482 m_opaque_sp->GetFilterDescription (s.get()); 483 const size_t num_locations = m_opaque_sp->GetNumLocations (); 484 s.Printf(", locations = %llu", (uint64_t)num_locations); 485 return true; 486 } 487 s.Printf ("No value"); 488 return false; 489 } 490 491 bool 492 SBBreakpoint::PrivateBreakpointHitCallback 493 ( 494 void *baton, 495 StoppointCallbackContext *ctx, 496 lldb::user_id_t break_id, 497 lldb::user_id_t break_loc_id 498 ) 499 { 500 ExecutionContext exe_ctx (ctx->exe_ctx_ref); 501 BreakpointSP bp_sp(exe_ctx.GetTargetRef().GetBreakpointList().FindBreakpointByID(break_id)); 502 if (baton && bp_sp) 503 { 504 CallbackData *data = (CallbackData *)baton; 505 lldb_private::Breakpoint *bp = bp_sp.get(); 506 if (bp && data->callback) 507 { 508 Process *process = exe_ctx.GetProcessPtr(); 509 if (process) 510 { 511 SBProcess sb_process (process->shared_from_this()); 512 SBThread sb_thread; 513 SBBreakpointLocation sb_location; 514 assert (bp_sp); 515 sb_location.SetLocation (bp_sp->FindLocationByID (break_loc_id)); 516 Thread *thread = exe_ctx.GetThreadPtr(); 517 if (thread) 518 sb_thread.SetThread(thread->shared_from_this()); 519 520 return data->callback (data->callback_baton, 521 sb_process, 522 sb_thread, 523 sb_location); 524 } 525 } 526 } 527 return true; // Return true if we should stop at this breakpoint 528 } 529 530 void 531 SBBreakpoint::SetCallback (BreakpointHitCallback callback, void *baton) 532 { 533 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 534 535 if (log) 536 log->Printf ("SBBreakpoint(%p)::SetCallback (callback=%p, baton=%p)", m_opaque_sp.get(), callback, baton); 537 538 if (m_opaque_sp) 539 { 540 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 541 BatonSP baton_sp(new SBBreakpointCallbackBaton (callback, baton)); 542 m_opaque_sp->SetCallback (SBBreakpoint::PrivateBreakpointHitCallback, baton_sp, false); 543 } 544 } 545 546 547 lldb_private::Breakpoint * 548 SBBreakpoint::operator->() const 549 { 550 return m_opaque_sp.get(); 551 } 552 553 lldb_private::Breakpoint * 554 SBBreakpoint::get() const 555 { 556 return m_opaque_sp.get(); 557 } 558 559 lldb::BreakpointSP & 560 SBBreakpoint::operator *() 561 { 562 return m_opaque_sp; 563 } 564 565 const lldb::BreakpointSP & 566 SBBreakpoint::operator *() const 567 { 568 return m_opaque_sp; 569 } 570 571 bool 572 SBBreakpoint::EventIsBreakpointEvent (const lldb::SBEvent &event) 573 { 574 return Breakpoint::BreakpointEventData::GetEventDataFromEvent(event.get()) != NULL; 575 576 } 577 578 BreakpointEventType 579 SBBreakpoint::GetBreakpointEventTypeFromEvent (const SBEvent& event) 580 { 581 if (event.IsValid()) 582 return Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event.GetSP()); 583 return eBreakpointEventTypeInvalidType; 584 } 585 586 SBBreakpoint 587 SBBreakpoint::GetBreakpointFromEvent (const lldb::SBEvent& event) 588 { 589 SBBreakpoint sb_breakpoint; 590 if (event.IsValid()) 591 sb_breakpoint.m_opaque_sp = Breakpoint::BreakpointEventData::GetBreakpointFromEvent (event.GetSP()); 592 return sb_breakpoint; 593 } 594 595 SBBreakpointLocation 596 SBBreakpoint::GetBreakpointLocationAtIndexFromEvent (const lldb::SBEvent& event, uint32_t loc_idx) 597 { 598 SBBreakpointLocation sb_breakpoint_loc; 599 if (event.IsValid()) 600 sb_breakpoint_loc.SetLocation (Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent (event.GetSP(), loc_idx)); 601 return sb_breakpoint_loc; 602 } 603 604 uint32_t 605 SBBreakpoint::GetNumBreakpointLocationsFromEvent (const lldb::SBEvent &event) 606 { 607 uint32_t num_locations = 0; 608 if (event.IsValid()) 609 num_locations = (Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent (event.GetSP())); 610 return num_locations; 611 } 612 613 614