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