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 // C Includes 11 // C++ Includes 12 // Other libraries and framework includes 13 // Project includes 14 #include "lldb/API/SBBreakpoint.h" 15 #include "lldb/API/SBBreakpointLocation.h" 16 #include "lldb/API/SBDebugger.h" 17 #include "lldb/API/SBEvent.h" 18 #include "lldb/API/SBProcess.h" 19 #include "lldb/API/SBStream.h" 20 #include "lldb/API/SBStringList.h" 21 #include "lldb/API/SBThread.h" 22 23 #include "lldb/Breakpoint/Breakpoint.h" 24 #include "lldb/Breakpoint/BreakpointIDList.h" 25 #include "lldb/Breakpoint/BreakpointLocation.h" 26 #include "lldb/Breakpoint/StoppointCallbackContext.h" 27 #include "lldb/Core/Address.h" 28 #include "lldb/Core/Debugger.h" 29 #include "lldb/Core/Log.h" 30 #include "lldb/Core/Stream.h" 31 #include "lldb/Core/StreamFile.h" 32 #include "lldb/Interpreter/CommandInterpreter.h" 33 #include "lldb/Interpreter/ScriptInterpreter.h" 34 #include "lldb/Target/Process.h" 35 #include "lldb/Target/SectionLoadList.h" 36 #include "lldb/Target/Target.h" 37 #include "lldb/Target/Thread.h" 38 #include "lldb/Target/ThreadSpec.h" 39 40 #include "lldb/lldb-enumerations.h" 41 42 #include "llvm/ADT/STLExtras.h" 43 44 using namespace lldb; 45 using namespace lldb_private; 46 47 struct CallbackData { 48 SBBreakpoint::BreakpointHitCallback callback; 49 void *callback_baton; 50 }; 51 52 class SBBreakpointCallbackBaton : public TypedBaton<CallbackData> { 53 public: 54 SBBreakpointCallbackBaton(SBBreakpoint::BreakpointHitCallback callback, 55 void *baton) 56 : TypedBaton(llvm::make_unique<CallbackData>()) { 57 getItem()->callback = callback; 58 getItem()->callback_baton = baton; 59 } 60 }; 61 62 SBBreakpoint::SBBreakpoint() : m_opaque_sp() {} 63 64 SBBreakpoint::SBBreakpoint(const SBBreakpoint &rhs) 65 : m_opaque_sp(rhs.m_opaque_sp) {} 66 67 SBBreakpoint::SBBreakpoint(const lldb::BreakpointSP &bp_sp) 68 : m_opaque_sp(bp_sp) {} 69 70 SBBreakpoint::~SBBreakpoint() = default; 71 72 const SBBreakpoint &SBBreakpoint::operator=(const SBBreakpoint &rhs) { 73 if (this != &rhs) 74 m_opaque_sp = rhs.m_opaque_sp; 75 return *this; 76 } 77 78 bool SBBreakpoint::operator==(const lldb::SBBreakpoint &rhs) { 79 if (m_opaque_sp && rhs.m_opaque_sp) 80 return m_opaque_sp.get() == rhs.m_opaque_sp.get(); 81 return false; 82 } 83 84 bool SBBreakpoint::operator!=(const lldb::SBBreakpoint &rhs) { 85 if (m_opaque_sp && rhs.m_opaque_sp) 86 return m_opaque_sp.get() != rhs.m_opaque_sp.get(); 87 return (m_opaque_sp && !rhs.m_opaque_sp) || (rhs.m_opaque_sp && !m_opaque_sp); 88 } 89 90 break_id_t SBBreakpoint::GetID() const { 91 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 92 93 break_id_t break_id = LLDB_INVALID_BREAK_ID; 94 if (m_opaque_sp) 95 break_id = m_opaque_sp->GetID(); 96 97 if (log) { 98 if (break_id == LLDB_INVALID_BREAK_ID) 99 log->Printf("SBBreakpoint(%p)::GetID () => LLDB_INVALID_BREAK_ID", 100 static_cast<void *>(m_opaque_sp.get())); 101 else 102 log->Printf("SBBreakpoint(%p)::GetID () => %u", 103 static_cast<void *>(m_opaque_sp.get()), break_id); 104 } 105 106 return break_id; 107 } 108 109 bool SBBreakpoint::IsValid() const { 110 if (!m_opaque_sp) 111 return false; 112 else if (m_opaque_sp->GetTarget().GetBreakpointByID(m_opaque_sp->GetID())) 113 return true; 114 else 115 return false; 116 } 117 118 void SBBreakpoint::ClearAllBreakpointSites() { 119 if (m_opaque_sp) { 120 std::lock_guard<std::recursive_mutex> guard( 121 m_opaque_sp->GetTarget().GetAPIMutex()); 122 m_opaque_sp->ClearAllBreakpointSites(); 123 } 124 } 125 126 SBBreakpointLocation SBBreakpoint::FindLocationByAddress(addr_t vm_addr) { 127 SBBreakpointLocation sb_bp_location; 128 129 if (m_opaque_sp) { 130 if (vm_addr != LLDB_INVALID_ADDRESS) { 131 std::lock_guard<std::recursive_mutex> guard( 132 m_opaque_sp->GetTarget().GetAPIMutex()); 133 Address address; 134 Target &target = m_opaque_sp->GetTarget(); 135 if (!target.GetSectionLoadList().ResolveLoadAddress(vm_addr, address)) { 136 address.SetRawAddress(vm_addr); 137 } 138 sb_bp_location.SetLocation(m_opaque_sp->FindLocationByAddress(address)); 139 } 140 } 141 return sb_bp_location; 142 } 143 144 break_id_t SBBreakpoint::FindLocationIDByAddress(addr_t vm_addr) { 145 break_id_t break_id = LLDB_INVALID_BREAK_ID; 146 147 if (m_opaque_sp && vm_addr != LLDB_INVALID_ADDRESS) { 148 std::lock_guard<std::recursive_mutex> guard( 149 m_opaque_sp->GetTarget().GetAPIMutex()); 150 Address address; 151 Target &target = m_opaque_sp->GetTarget(); 152 if (!target.GetSectionLoadList().ResolveLoadAddress(vm_addr, address)) { 153 address.SetRawAddress(vm_addr); 154 } 155 break_id = m_opaque_sp->FindLocationIDByAddress(address); 156 } 157 158 return break_id; 159 } 160 161 SBBreakpointLocation SBBreakpoint::FindLocationByID(break_id_t bp_loc_id) { 162 SBBreakpointLocation sb_bp_location; 163 164 if (m_opaque_sp) { 165 std::lock_guard<std::recursive_mutex> guard( 166 m_opaque_sp->GetTarget().GetAPIMutex()); 167 sb_bp_location.SetLocation(m_opaque_sp->FindLocationByID(bp_loc_id)); 168 } 169 170 return sb_bp_location; 171 } 172 173 SBBreakpointLocation SBBreakpoint::GetLocationAtIndex(uint32_t index) { 174 SBBreakpointLocation sb_bp_location; 175 176 if (m_opaque_sp) { 177 std::lock_guard<std::recursive_mutex> guard( 178 m_opaque_sp->GetTarget().GetAPIMutex()); 179 sb_bp_location.SetLocation(m_opaque_sp->GetLocationAtIndex(index)); 180 } 181 182 return sb_bp_location; 183 } 184 185 void SBBreakpoint::SetEnabled(bool enable) { 186 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 187 188 if (log) 189 log->Printf("SBBreakpoint(%p)::SetEnabled (enabled=%i)", 190 static_cast<void *>(m_opaque_sp.get()), enable); 191 192 if (m_opaque_sp) { 193 std::lock_guard<std::recursive_mutex> guard( 194 m_opaque_sp->GetTarget().GetAPIMutex()); 195 m_opaque_sp->SetEnabled(enable); 196 } 197 } 198 199 bool SBBreakpoint::IsEnabled() { 200 if (m_opaque_sp) { 201 std::lock_guard<std::recursive_mutex> guard( 202 m_opaque_sp->GetTarget().GetAPIMutex()); 203 return m_opaque_sp->IsEnabled(); 204 } else 205 return false; 206 } 207 208 void SBBreakpoint::SetOneShot(bool one_shot) { 209 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 210 211 if (log) 212 log->Printf("SBBreakpoint(%p)::SetOneShot (one_shot=%i)", 213 static_cast<void *>(m_opaque_sp.get()), one_shot); 214 215 if (m_opaque_sp) { 216 std::lock_guard<std::recursive_mutex> guard( 217 m_opaque_sp->GetTarget().GetAPIMutex()); 218 m_opaque_sp->SetOneShot(one_shot); 219 } 220 } 221 222 bool SBBreakpoint::IsOneShot() const { 223 if (m_opaque_sp) { 224 std::lock_guard<std::recursive_mutex> guard( 225 m_opaque_sp->GetTarget().GetAPIMutex()); 226 return m_opaque_sp->IsOneShot(); 227 } else 228 return false; 229 } 230 231 bool SBBreakpoint::IsInternal() { 232 if (m_opaque_sp) { 233 std::lock_guard<std::recursive_mutex> guard( 234 m_opaque_sp->GetTarget().GetAPIMutex()); 235 return m_opaque_sp->IsInternal(); 236 } else 237 return false; 238 } 239 240 void SBBreakpoint::SetIgnoreCount(uint32_t count) { 241 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 242 243 if (log) 244 log->Printf("SBBreakpoint(%p)::SetIgnoreCount (count=%u)", 245 static_cast<void *>(m_opaque_sp.get()), count); 246 247 if (m_opaque_sp) { 248 std::lock_guard<std::recursive_mutex> guard( 249 m_opaque_sp->GetTarget().GetAPIMutex()); 250 m_opaque_sp->SetIgnoreCount(count); 251 } 252 } 253 254 void SBBreakpoint::SetCondition(const char *condition) { 255 if (m_opaque_sp) { 256 std::lock_guard<std::recursive_mutex> guard( 257 m_opaque_sp->GetTarget().GetAPIMutex()); 258 m_opaque_sp->SetCondition(condition); 259 } 260 } 261 262 const char *SBBreakpoint::GetCondition() { 263 if (m_opaque_sp) { 264 std::lock_guard<std::recursive_mutex> guard( 265 m_opaque_sp->GetTarget().GetAPIMutex()); 266 return m_opaque_sp->GetConditionText(); 267 } 268 return nullptr; 269 } 270 271 uint32_t SBBreakpoint::GetHitCount() const { 272 uint32_t count = 0; 273 if (m_opaque_sp) { 274 std::lock_guard<std::recursive_mutex> guard( 275 m_opaque_sp->GetTarget().GetAPIMutex()); 276 count = m_opaque_sp->GetHitCount(); 277 } 278 279 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 280 if (log) 281 log->Printf("SBBreakpoint(%p)::GetHitCount () => %u", 282 static_cast<void *>(m_opaque_sp.get()), count); 283 284 return count; 285 } 286 287 uint32_t SBBreakpoint::GetIgnoreCount() const { 288 uint32_t count = 0; 289 if (m_opaque_sp) { 290 std::lock_guard<std::recursive_mutex> guard( 291 m_opaque_sp->GetTarget().GetAPIMutex()); 292 count = m_opaque_sp->GetIgnoreCount(); 293 } 294 295 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 296 if (log) 297 log->Printf("SBBreakpoint(%p)::GetIgnoreCount () => %u", 298 static_cast<void *>(m_opaque_sp.get()), count); 299 300 return count; 301 } 302 303 void SBBreakpoint::SetThreadID(tid_t tid) { 304 if (m_opaque_sp) { 305 std::lock_guard<std::recursive_mutex> guard( 306 m_opaque_sp->GetTarget().GetAPIMutex()); 307 m_opaque_sp->SetThreadID(tid); 308 } 309 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 310 if (log) 311 log->Printf("SBBreakpoint(%p)::SetThreadID (tid=0x%4.4" PRIx64 ")", 312 static_cast<void *>(m_opaque_sp.get()), tid); 313 } 314 315 tid_t SBBreakpoint::GetThreadID() { 316 tid_t tid = LLDB_INVALID_THREAD_ID; 317 if (m_opaque_sp) { 318 std::lock_guard<std::recursive_mutex> guard( 319 m_opaque_sp->GetTarget().GetAPIMutex()); 320 tid = m_opaque_sp->GetThreadID(); 321 } 322 323 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 324 if (log) 325 log->Printf("SBBreakpoint(%p)::GetThreadID () => 0x%4.4" PRIx64, 326 static_cast<void *>(m_opaque_sp.get()), tid); 327 return tid; 328 } 329 330 void SBBreakpoint::SetThreadIndex(uint32_t index) { 331 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 332 if (log) 333 log->Printf("SBBreakpoint(%p)::SetThreadIndex (%u)", 334 static_cast<void *>(m_opaque_sp.get()), index); 335 if (m_opaque_sp) { 336 std::lock_guard<std::recursive_mutex> guard( 337 m_opaque_sp->GetTarget().GetAPIMutex()); 338 m_opaque_sp->GetOptions()->GetThreadSpec()->SetIndex(index); 339 } 340 } 341 342 uint32_t SBBreakpoint::GetThreadIndex() const { 343 uint32_t thread_idx = UINT32_MAX; 344 if (m_opaque_sp) { 345 std::lock_guard<std::recursive_mutex> guard( 346 m_opaque_sp->GetTarget().GetAPIMutex()); 347 const ThreadSpec *thread_spec = 348 m_opaque_sp->GetOptions()->GetThreadSpecNoCreate(); 349 if (thread_spec != nullptr) 350 thread_idx = thread_spec->GetIndex(); 351 } 352 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 353 if (log) 354 log->Printf("SBBreakpoint(%p)::GetThreadIndex () => %u", 355 static_cast<void *>(m_opaque_sp.get()), thread_idx); 356 357 return thread_idx; 358 } 359 360 void SBBreakpoint::SetThreadName(const char *thread_name) { 361 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 362 if (log) 363 log->Printf("SBBreakpoint(%p)::SetThreadName (%s)", 364 static_cast<void *>(m_opaque_sp.get()), thread_name); 365 366 if (m_opaque_sp) { 367 std::lock_guard<std::recursive_mutex> guard( 368 m_opaque_sp->GetTarget().GetAPIMutex()); 369 m_opaque_sp->GetOptions()->GetThreadSpec()->SetName(thread_name); 370 } 371 } 372 373 const char *SBBreakpoint::GetThreadName() const { 374 const char *name = nullptr; 375 if (m_opaque_sp) { 376 std::lock_guard<std::recursive_mutex> guard( 377 m_opaque_sp->GetTarget().GetAPIMutex()); 378 const ThreadSpec *thread_spec = 379 m_opaque_sp->GetOptions()->GetThreadSpecNoCreate(); 380 if (thread_spec != nullptr) 381 name = thread_spec->GetName(); 382 } 383 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 384 if (log) 385 log->Printf("SBBreakpoint(%p)::GetThreadName () => %s", 386 static_cast<void *>(m_opaque_sp.get()), name); 387 388 return name; 389 } 390 391 void SBBreakpoint::SetQueueName(const char *queue_name) { 392 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 393 if (log) 394 log->Printf("SBBreakpoint(%p)::SetQueueName (%s)", 395 static_cast<void *>(m_opaque_sp.get()), queue_name); 396 if (m_opaque_sp) { 397 std::lock_guard<std::recursive_mutex> guard( 398 m_opaque_sp->GetTarget().GetAPIMutex()); 399 m_opaque_sp->GetOptions()->GetThreadSpec()->SetQueueName(queue_name); 400 } 401 } 402 403 const char *SBBreakpoint::GetQueueName() const { 404 const char *name = nullptr; 405 if (m_opaque_sp) { 406 std::lock_guard<std::recursive_mutex> guard( 407 m_opaque_sp->GetTarget().GetAPIMutex()); 408 const ThreadSpec *thread_spec = 409 m_opaque_sp->GetOptions()->GetThreadSpecNoCreate(); 410 if (thread_spec) 411 name = thread_spec->GetQueueName(); 412 } 413 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 414 if (log) 415 log->Printf("SBBreakpoint(%p)::GetQueueName () => %s", 416 static_cast<void *>(m_opaque_sp.get()), name); 417 418 return name; 419 } 420 421 size_t SBBreakpoint::GetNumResolvedLocations() const { 422 size_t num_resolved = 0; 423 if (m_opaque_sp) { 424 std::lock_guard<std::recursive_mutex> guard( 425 m_opaque_sp->GetTarget().GetAPIMutex()); 426 num_resolved = m_opaque_sp->GetNumResolvedLocations(); 427 } 428 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 429 if (log) 430 log->Printf("SBBreakpoint(%p)::GetNumResolvedLocations () => %" PRIu64, 431 static_cast<void *>(m_opaque_sp.get()), 432 static_cast<uint64_t>(num_resolved)); 433 return num_resolved; 434 } 435 436 size_t SBBreakpoint::GetNumLocations() const { 437 size_t num_locs = 0; 438 if (m_opaque_sp) { 439 std::lock_guard<std::recursive_mutex> guard( 440 m_opaque_sp->GetTarget().GetAPIMutex()); 441 num_locs = m_opaque_sp->GetNumLocations(); 442 } 443 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 444 if (log) 445 log->Printf("SBBreakpoint(%p)::GetNumLocations () => %" PRIu64, 446 static_cast<void *>(m_opaque_sp.get()), 447 static_cast<uint64_t>(num_locs)); 448 return num_locs; 449 } 450 451 void SBBreakpoint::SetCommandLineCommands(SBStringList &commands) { 452 if (!m_opaque_sp) 453 return; 454 if (commands.GetSize() == 0) 455 return; 456 457 std::lock_guard<std::recursive_mutex> guard( 458 m_opaque_sp->GetTarget().GetAPIMutex()); 459 std::unique_ptr<BreakpointOptions::CommandData> cmd_data_up( 460 new BreakpointOptions::CommandData(*commands, eScriptLanguageNone)); 461 462 m_opaque_sp->GetOptions()->SetCommandDataCallback(cmd_data_up); 463 } 464 465 bool SBBreakpoint::GetCommandLineCommands(SBStringList &commands) { 466 if (!m_opaque_sp) 467 return false; 468 StringList command_list; 469 bool has_commands = 470 m_opaque_sp->GetOptions()->GetCommandLineCallbacks(command_list); 471 if (has_commands) 472 commands.AppendList(command_list); 473 return has_commands; 474 } 475 476 bool SBBreakpoint::GetDescription(SBStream &s) { 477 return GetDescription(s, true); 478 } 479 480 bool SBBreakpoint::GetDescription(SBStream &s, bool include_locations) { 481 if (m_opaque_sp) { 482 std::lock_guard<std::recursive_mutex> guard( 483 m_opaque_sp->GetTarget().GetAPIMutex()); 484 s.Printf("SBBreakpoint: id = %i, ", m_opaque_sp->GetID()); 485 m_opaque_sp->GetResolverDescription(s.get()); 486 m_opaque_sp->GetFilterDescription(s.get()); 487 if (include_locations) { 488 const size_t num_locations = m_opaque_sp->GetNumLocations(); 489 s.Printf(", locations = %" PRIu64, (uint64_t)num_locations); 490 } 491 return true; 492 } 493 s.Printf("No value"); 494 return false; 495 } 496 497 bool SBBreakpoint::PrivateBreakpointHitCallback(void *baton, 498 StoppointCallbackContext *ctx, 499 lldb::user_id_t break_id, 500 lldb::user_id_t break_loc_id) { 501 ExecutionContext exe_ctx(ctx->exe_ctx_ref); 502 BreakpointSP bp_sp( 503 exe_ctx.GetTargetRef().GetBreakpointList().FindBreakpointByID(break_id)); 504 if (baton && bp_sp) { 505 CallbackData *data = (CallbackData *)baton; 506 lldb_private::Breakpoint *bp = bp_sp.get(); 507 if (bp && data->callback) { 508 Process *process = exe_ctx.GetProcessPtr(); 509 if (process) { 510 SBProcess sb_process(process->shared_from_this()); 511 SBThread sb_thread; 512 SBBreakpointLocation sb_location; 513 assert(bp_sp); 514 sb_location.SetLocation(bp_sp->FindLocationByID(break_loc_id)); 515 Thread *thread = exe_ctx.GetThreadPtr(); 516 if (thread) 517 sb_thread.SetThread(thread->shared_from_this()); 518 519 return data->callback(data->callback_baton, sb_process, sb_thread, 520 sb_location); 521 } 522 } 523 } 524 return true; // Return true if we should stop at this breakpoint 525 } 526 527 void SBBreakpoint::SetCallback(BreakpointHitCallback callback, void *baton) { 528 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 529 530 if (log) { 531 void *pointer = &callback; 532 log->Printf("SBBreakpoint(%p)::SetCallback (callback=%p, baton=%p)", 533 static_cast<void *>(m_opaque_sp.get()), 534 *static_cast<void **>(&pointer), static_cast<void *>(baton)); 535 } 536 537 if (m_opaque_sp) { 538 std::lock_guard<std::recursive_mutex> guard( 539 m_opaque_sp->GetTarget().GetAPIMutex()); 540 BatonSP baton_sp(new SBBreakpointCallbackBaton(callback, baton)); 541 m_opaque_sp->SetCallback(SBBreakpoint::PrivateBreakpointHitCallback, 542 baton_sp, false); 543 } 544 } 545 546 void SBBreakpoint::SetScriptCallbackFunction( 547 const char *callback_function_name) { 548 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 549 550 if (log) 551 log->Printf("SBBreakpoint(%p)::SetScriptCallbackFunction (callback=%s)", 552 static_cast<void *>(m_opaque_sp.get()), callback_function_name); 553 554 if (m_opaque_sp) { 555 std::lock_guard<std::recursive_mutex> guard( 556 m_opaque_sp->GetTarget().GetAPIMutex()); 557 BreakpointOptions *bp_options = m_opaque_sp->GetOptions(); 558 m_opaque_sp->GetTarget() 559 .GetDebugger() 560 .GetCommandInterpreter() 561 .GetScriptInterpreter() 562 ->SetBreakpointCommandCallbackFunction(bp_options, 563 callback_function_name); 564 } 565 } 566 567 SBError SBBreakpoint::SetScriptCallbackBody(const char *callback_body_text) { 568 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 569 570 if (log) 571 log->Printf("SBBreakpoint(%p)::SetScriptCallbackBody: callback body:\n%s)", 572 static_cast<void *>(m_opaque_sp.get()), callback_body_text); 573 574 SBError sb_error; 575 if (m_opaque_sp) { 576 std::lock_guard<std::recursive_mutex> guard( 577 m_opaque_sp->GetTarget().GetAPIMutex()); 578 BreakpointOptions *bp_options = m_opaque_sp->GetOptions(); 579 Error error = 580 m_opaque_sp->GetTarget() 581 .GetDebugger() 582 .GetCommandInterpreter() 583 .GetScriptInterpreter() 584 ->SetBreakpointCommandCallback(bp_options, callback_body_text); 585 sb_error.SetError(error); 586 } else 587 sb_error.SetErrorString("invalid breakpoint"); 588 589 return sb_error; 590 } 591 592 bool SBBreakpoint::AddName(const char *new_name) { 593 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 594 595 if (log) 596 log->Printf("SBBreakpoint(%p)::AddName (name=%s)", 597 static_cast<void *>(m_opaque_sp.get()), new_name); 598 599 if (m_opaque_sp) { 600 std::lock_guard<std::recursive_mutex> guard( 601 m_opaque_sp->GetTarget().GetAPIMutex()); 602 Error error; // Think I'm just going to swallow the error here, it's 603 // probably more annoying to have to provide it. 604 return m_opaque_sp->AddName(new_name, error); 605 } 606 607 return false; 608 } 609 610 void SBBreakpoint::RemoveName(const char *name_to_remove) { 611 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 612 613 if (log) 614 log->Printf("SBBreakpoint(%p)::RemoveName (name=%s)", 615 static_cast<void *>(m_opaque_sp.get()), name_to_remove); 616 617 if (m_opaque_sp) { 618 std::lock_guard<std::recursive_mutex> guard( 619 m_opaque_sp->GetTarget().GetAPIMutex()); 620 m_opaque_sp->RemoveName(name_to_remove); 621 } 622 } 623 624 bool SBBreakpoint::MatchesName(const char *name) { 625 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 626 627 if (log) 628 log->Printf("SBBreakpoint(%p)::MatchesName (name=%s)", 629 static_cast<void *>(m_opaque_sp.get()), name); 630 631 if (m_opaque_sp) { 632 std::lock_guard<std::recursive_mutex> guard( 633 m_opaque_sp->GetTarget().GetAPIMutex()); 634 return m_opaque_sp->MatchesName(name); 635 } 636 637 return false; 638 } 639 640 void SBBreakpoint::GetNames(SBStringList &names) { 641 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 642 643 if (log) 644 log->Printf("SBBreakpoint(%p)::GetNames ()", 645 static_cast<void *>(m_opaque_sp.get())); 646 647 if (m_opaque_sp) { 648 std::lock_guard<std::recursive_mutex> guard( 649 m_opaque_sp->GetTarget().GetAPIMutex()); 650 std::vector<std::string> names_vec; 651 m_opaque_sp->GetNames(names_vec); 652 for (std::string name : names_vec) { 653 names.AppendString(name.c_str()); 654 } 655 } 656 } 657 658 lldb_private::Breakpoint *SBBreakpoint::operator->() const { 659 return m_opaque_sp.get(); 660 } 661 662 lldb_private::Breakpoint *SBBreakpoint::get() const { 663 return m_opaque_sp.get(); 664 } 665 666 lldb::BreakpointSP &SBBreakpoint::operator*() { return m_opaque_sp; } 667 668 const lldb::BreakpointSP &SBBreakpoint::operator*() const { 669 return m_opaque_sp; 670 } 671 672 bool SBBreakpoint::EventIsBreakpointEvent(const lldb::SBEvent &event) { 673 return Breakpoint::BreakpointEventData::GetEventDataFromEvent(event.get()) != 674 nullptr; 675 } 676 677 BreakpointEventType 678 SBBreakpoint::GetBreakpointEventTypeFromEvent(const SBEvent &event) { 679 if (event.IsValid()) 680 return Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent( 681 event.GetSP()); 682 return eBreakpointEventTypeInvalidType; 683 } 684 685 SBBreakpoint SBBreakpoint::GetBreakpointFromEvent(const lldb::SBEvent &event) { 686 SBBreakpoint sb_breakpoint; 687 if (event.IsValid()) 688 sb_breakpoint.m_opaque_sp = 689 Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event.GetSP()); 690 return sb_breakpoint; 691 } 692 693 SBBreakpointLocation 694 SBBreakpoint::GetBreakpointLocationAtIndexFromEvent(const lldb::SBEvent &event, 695 uint32_t loc_idx) { 696 SBBreakpointLocation sb_breakpoint_loc; 697 if (event.IsValid()) 698 sb_breakpoint_loc.SetLocation( 699 Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent( 700 event.GetSP(), loc_idx)); 701 return sb_breakpoint_loc; 702 } 703 704 uint32_t 705 SBBreakpoint::GetNumBreakpointLocationsFromEvent(const lldb::SBEvent &event) { 706 uint32_t num_locations = 0; 707 if (event.IsValid()) 708 num_locations = 709 (Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent( 710 event.GetSP())); 711 return num_locations; 712 } 713 714 // This is simple collection of breakpoint id's and their target. 715 class lldb::SBBreakpointListImpl { 716 public: 717 SBBreakpointListImpl(SBTarget &target) : m_target_wp() { 718 if (target.IsValid()) 719 m_target_wp = target.GetSP(); 720 } 721 722 ~SBBreakpointListImpl() = default; 723 724 size_t GetSize() { return m_break_ids.size(); } 725 726 BreakpointSP GetBreakpointAtIndex(size_t idx) { 727 if (idx >= m_break_ids.size()) 728 return BreakpointSP(); 729 TargetSP target_sp = m_target_wp.lock(); 730 if (!target_sp) 731 return BreakpointSP(); 732 lldb::break_id_t bp_id = m_break_ids[idx]; 733 return target_sp->GetBreakpointList().FindBreakpointByID(bp_id); 734 } 735 736 BreakpointSP FindBreakpointByID(lldb::break_id_t desired_id) { 737 TargetSP target_sp = m_target_wp.lock(); 738 if (!target_sp) 739 return BreakpointSP(); 740 741 for (lldb::break_id_t &break_id : m_break_ids) { 742 if (break_id == desired_id) 743 return target_sp->GetBreakpointList().FindBreakpointByID(break_id); 744 } 745 return BreakpointSP(); 746 } 747 748 bool Append(Breakpoint &bkpt) { 749 TargetSP target_sp = m_target_wp.lock(); 750 if (!target_sp) 751 return false; 752 if (bkpt.GetTargetSP() != target_sp) 753 return false; 754 m_break_ids.push_back(bkpt.GetID()); 755 return true; 756 } 757 758 bool AppendIfUnique(Breakpoint &bkpt) { 759 TargetSP target_sp = m_target_wp.lock(); 760 if (!target_sp) 761 return false; 762 if (bkpt.GetTargetSP() != target_sp) 763 return false; 764 lldb::break_id_t bp_id = bkpt.GetID(); 765 if (find(m_break_ids.begin(), m_break_ids.end(), bp_id) == 766 m_break_ids.end()) 767 return false; 768 769 m_break_ids.push_back(bkpt.GetID()); 770 return true; 771 } 772 773 bool AppendByID(lldb::break_id_t id) { 774 TargetSP target_sp = m_target_wp.lock(); 775 if (!target_sp) 776 return false; 777 if (id == LLDB_INVALID_BREAK_ID) 778 return false; 779 m_break_ids.push_back(id); 780 return true; 781 } 782 783 void Clear() { m_break_ids.clear(); } 784 785 void CopyToBreakpointIDList(lldb_private::BreakpointIDList &bp_list) { 786 for (lldb::break_id_t id : m_break_ids) { 787 bp_list.AddBreakpointID(BreakpointID(id)); 788 } 789 } 790 791 TargetSP GetTarget() { return m_target_wp.lock(); } 792 793 private: 794 std::vector<lldb::break_id_t> m_break_ids; 795 TargetWP m_target_wp; 796 }; 797 798 SBBreakpointList::SBBreakpointList(SBTarget &target) 799 : m_opaque_sp(new lldb::SBBreakpointListImpl(target)) {} 800 801 SBBreakpointList::~SBBreakpointList() {} 802 803 size_t SBBreakpointList::GetSize() const { 804 if (!m_opaque_sp) 805 return 0; 806 else 807 return m_opaque_sp->GetSize(); 808 } 809 810 SBBreakpoint SBBreakpointList::GetBreakpointAtIndex(size_t idx) { 811 if (!m_opaque_sp) 812 return SBBreakpoint(); 813 814 BreakpointSP bkpt_sp = m_opaque_sp->GetBreakpointAtIndex(idx); 815 return SBBreakpoint(bkpt_sp); 816 } 817 818 SBBreakpoint SBBreakpointList::FindBreakpointByID(lldb::break_id_t id) { 819 if (!m_opaque_sp) 820 return SBBreakpoint(); 821 BreakpointSP bkpt_sp = m_opaque_sp->FindBreakpointByID(id); 822 return SBBreakpoint(bkpt_sp); 823 } 824 825 void SBBreakpointList::Append(const SBBreakpoint &sb_bkpt) { 826 if (!sb_bkpt.IsValid()) 827 return; 828 if (!m_opaque_sp) 829 return; 830 m_opaque_sp->Append(*sb_bkpt.get()); 831 } 832 833 void SBBreakpointList::AppendByID(lldb::break_id_t id) { 834 if (!m_opaque_sp) 835 return; 836 m_opaque_sp->AppendByID(id); 837 } 838 839 bool SBBreakpointList::AppendIfUnique(const SBBreakpoint &sb_bkpt) { 840 if (!sb_bkpt.IsValid()) 841 return false; 842 if (!m_opaque_sp) 843 return false; 844 return m_opaque_sp->AppendIfUnique(*sb_bkpt.get()); 845 } 846 847 void SBBreakpointList::Clear() { 848 if (m_opaque_sp) 849 m_opaque_sp->Clear(); 850 } 851 852 void SBBreakpointList::CopyToBreakpointIDList( 853 lldb_private::BreakpointIDList &bp_id_list) { 854 if (m_opaque_sp) 855 m_opaque_sp->CopyToBreakpointIDList(bp_id_list); 856 } 857