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