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