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 return nullptr; 289 290 std::lock_guard<std::recursive_mutex> guard( 291 bkpt_sp->GetTarget().GetAPIMutex()); 292 return ConstString(bkpt_sp->GetConditionText()).GetCString(); 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 BreakpointSP bkpt_sp = GetSP(); 415 if (!bkpt_sp) 416 return nullptr; 417 418 std::lock_guard<std::recursive_mutex> guard( 419 bkpt_sp->GetTarget().GetAPIMutex()); 420 if (const ThreadSpec *thread_spec = 421 bkpt_sp->GetOptions().GetThreadSpecNoCreate()) 422 return ConstString(thread_spec->GetName()).GetCString(); 423 424 return nullptr; 425 } 426 427 void SBBreakpoint::SetQueueName(const char *queue_name) { 428 LLDB_INSTRUMENT_VA(this, queue_name); 429 430 BreakpointSP bkpt_sp = GetSP(); 431 if (bkpt_sp) { 432 std::lock_guard<std::recursive_mutex> guard( 433 bkpt_sp->GetTarget().GetAPIMutex()); 434 bkpt_sp->GetOptions().GetThreadSpec()->SetQueueName(queue_name); 435 } 436 } 437 438 const char *SBBreakpoint::GetQueueName() const { 439 LLDB_INSTRUMENT_VA(this); 440 441 BreakpointSP bkpt_sp = GetSP(); 442 if (!bkpt_sp) 443 return nullptr; 444 445 std::lock_guard<std::recursive_mutex> guard( 446 bkpt_sp->GetTarget().GetAPIMutex()); 447 if (const ThreadSpec *thread_spec = 448 bkpt_sp->GetOptions().GetThreadSpecNoCreate()) 449 return ConstString(thread_spec->GetQueueName()).GetCString(); 450 451 return nullptr; 452 } 453 454 size_t SBBreakpoint::GetNumResolvedLocations() const { 455 LLDB_INSTRUMENT_VA(this); 456 457 size_t num_resolved = 0; 458 BreakpointSP bkpt_sp = GetSP(); 459 if (bkpt_sp) { 460 std::lock_guard<std::recursive_mutex> guard( 461 bkpt_sp->GetTarget().GetAPIMutex()); 462 num_resolved = bkpt_sp->GetNumResolvedLocations(); 463 } 464 return num_resolved; 465 } 466 467 size_t SBBreakpoint::GetNumLocations() const { 468 LLDB_INSTRUMENT_VA(this); 469 470 BreakpointSP bkpt_sp = GetSP(); 471 size_t num_locs = 0; 472 if (bkpt_sp) { 473 std::lock_guard<std::recursive_mutex> guard( 474 bkpt_sp->GetTarget().GetAPIMutex()); 475 num_locs = bkpt_sp->GetNumLocations(); 476 } 477 return num_locs; 478 } 479 480 void SBBreakpoint::SetCommandLineCommands(SBStringList &commands) { 481 LLDB_INSTRUMENT_VA(this, commands); 482 483 BreakpointSP bkpt_sp = GetSP(); 484 if (!bkpt_sp) 485 return; 486 if (commands.GetSize() == 0) 487 return; 488 489 std::lock_guard<std::recursive_mutex> guard( 490 bkpt_sp->GetTarget().GetAPIMutex()); 491 std::unique_ptr<BreakpointOptions::CommandData> cmd_data_up( 492 new BreakpointOptions::CommandData(*commands, eScriptLanguageNone)); 493 494 bkpt_sp->GetOptions().SetCommandDataCallback(cmd_data_up); 495 } 496 497 bool SBBreakpoint::GetCommandLineCommands(SBStringList &commands) { 498 LLDB_INSTRUMENT_VA(this, commands); 499 500 BreakpointSP bkpt_sp = GetSP(); 501 if (!bkpt_sp) 502 return false; 503 StringList command_list; 504 bool has_commands = 505 bkpt_sp->GetOptions().GetCommandLineCallbacks(command_list); 506 if (has_commands) 507 commands.AppendList(command_list); 508 return has_commands; 509 } 510 511 bool SBBreakpoint::GetDescription(SBStream &s) { 512 LLDB_INSTRUMENT_VA(this, s); 513 514 return GetDescription(s, true); 515 } 516 517 bool SBBreakpoint::GetDescription(SBStream &s, bool include_locations) { 518 LLDB_INSTRUMENT_VA(this, s, include_locations); 519 520 BreakpointSP bkpt_sp = GetSP(); 521 if (bkpt_sp) { 522 std::lock_guard<std::recursive_mutex> guard( 523 bkpt_sp->GetTarget().GetAPIMutex()); 524 s.Printf("SBBreakpoint: id = %i, ", bkpt_sp->GetID()); 525 bkpt_sp->GetResolverDescription(s.get()); 526 bkpt_sp->GetFilterDescription(s.get()); 527 if (include_locations) { 528 const size_t num_locations = bkpt_sp->GetNumLocations(); 529 s.Printf(", locations = %" PRIu64, (uint64_t)num_locations); 530 } 531 return true; 532 } 533 s.Printf("No value"); 534 return false; 535 } 536 537 SBError SBBreakpoint::AddLocation(SBAddress &address) { 538 LLDB_INSTRUMENT_VA(this, address); 539 540 BreakpointSP bkpt_sp = GetSP(); 541 SBError error; 542 543 if (!address.IsValid()) { 544 error.SetErrorString("Can't add an invalid address."); 545 return error; 546 } 547 548 if (!bkpt_sp) { 549 error.SetErrorString("No breakpoint to add a location to."); 550 return error; 551 } 552 553 if (!llvm::isa<BreakpointResolverScripted>(bkpt_sp->GetResolver().get())) { 554 error.SetErrorString("Only a scripted resolver can add locations."); 555 return error; 556 } 557 558 if (bkpt_sp->GetSearchFilter()->AddressPasses(address.ref())) 559 bkpt_sp->AddLocation(address.ref()); 560 else { 561 StreamString s; 562 address.get()->Dump(&s, &bkpt_sp->GetTarget(), 563 Address::DumpStyleModuleWithFileAddress); 564 error.SetErrorStringWithFormat("Address: %s didn't pass the filter.", 565 s.GetData()); 566 } 567 return error; 568 } 569 570 SBStructuredData SBBreakpoint::SerializeToStructuredData() { 571 LLDB_INSTRUMENT_VA(this); 572 573 SBStructuredData data; 574 BreakpointSP bkpt_sp = GetSP(); 575 576 if (!bkpt_sp) 577 return data; 578 579 StructuredData::ObjectSP bkpt_dict = bkpt_sp->SerializeToStructuredData(); 580 data.m_impl_up->SetObjectSP(bkpt_dict); 581 return data; 582 } 583 584 void SBBreakpoint::SetCallback(SBBreakpointHitCallback callback, void *baton) { 585 LLDB_INSTRUMENT_VA(this, callback, baton); 586 587 BreakpointSP bkpt_sp = GetSP(); 588 589 if (bkpt_sp) { 590 std::lock_guard<std::recursive_mutex> guard( 591 bkpt_sp->GetTarget().GetAPIMutex()); 592 BatonSP baton_sp(new SBBreakpointCallbackBaton(callback, baton)); 593 bkpt_sp->SetCallback(SBBreakpointCallbackBaton 594 ::PrivateBreakpointHitCallback, baton_sp, 595 false); 596 } 597 } 598 599 void SBBreakpoint::SetScriptCallbackFunction( 600 const char *callback_function_name) { 601 LLDB_INSTRUMENT_VA(this, callback_function_name); 602 SBStructuredData empty_args; 603 SetScriptCallbackFunction(callback_function_name, empty_args); 604 } 605 606 SBError SBBreakpoint::SetScriptCallbackFunction( 607 const char *callback_function_name, 608 SBStructuredData &extra_args) { 609 LLDB_INSTRUMENT_VA(this, callback_function_name, extra_args); 610 SBError sb_error; 611 BreakpointSP bkpt_sp = GetSP(); 612 613 if (bkpt_sp) { 614 Status error; 615 std::lock_guard<std::recursive_mutex> guard( 616 bkpt_sp->GetTarget().GetAPIMutex()); 617 BreakpointOptions &bp_options = bkpt_sp->GetOptions(); 618 error = bkpt_sp->GetTarget() 619 .GetDebugger() 620 .GetScriptInterpreter() 621 ->SetBreakpointCommandCallbackFunction(bp_options, 622 callback_function_name, 623 extra_args.m_impl_up 624 ->GetObjectSP()); 625 sb_error.SetError(error); 626 } else 627 sb_error.SetErrorString("invalid breakpoint"); 628 629 return sb_error; 630 } 631 632 SBError SBBreakpoint::SetScriptCallbackBody(const char *callback_body_text) { 633 LLDB_INSTRUMENT_VA(this, callback_body_text); 634 635 BreakpointSP bkpt_sp = GetSP(); 636 637 SBError sb_error; 638 if (bkpt_sp) { 639 std::lock_guard<std::recursive_mutex> guard( 640 bkpt_sp->GetTarget().GetAPIMutex()); 641 BreakpointOptions &bp_options = bkpt_sp->GetOptions(); 642 Status error = 643 bkpt_sp->GetTarget() 644 .GetDebugger() 645 .GetScriptInterpreter() 646 ->SetBreakpointCommandCallback(bp_options, callback_body_text, 647 /*is_callback=*/false); 648 sb_error.SetError(error); 649 } else 650 sb_error.SetErrorString("invalid breakpoint"); 651 652 return sb_error; 653 } 654 655 bool SBBreakpoint::AddName(const char *new_name) { 656 LLDB_INSTRUMENT_VA(this, new_name); 657 658 SBError status = AddNameWithErrorHandling(new_name); 659 return status.Success(); 660 } 661 662 SBError SBBreakpoint::AddNameWithErrorHandling(const char *new_name) { 663 LLDB_INSTRUMENT_VA(this, new_name); 664 665 BreakpointSP bkpt_sp = GetSP(); 666 667 SBError status; 668 if (bkpt_sp) { 669 std::lock_guard<std::recursive_mutex> guard( 670 bkpt_sp->GetTarget().GetAPIMutex()); 671 Status error; 672 bkpt_sp->GetTarget().AddNameToBreakpoint(bkpt_sp, new_name, error); 673 status.SetError(error); 674 } else { 675 status.SetErrorString("invalid breakpoint"); 676 } 677 678 return status; 679 } 680 681 void SBBreakpoint::RemoveName(const char *name_to_remove) { 682 LLDB_INSTRUMENT_VA(this, name_to_remove); 683 684 BreakpointSP bkpt_sp = GetSP(); 685 686 if (bkpt_sp) { 687 std::lock_guard<std::recursive_mutex> guard( 688 bkpt_sp->GetTarget().GetAPIMutex()); 689 bkpt_sp->GetTarget().RemoveNameFromBreakpoint(bkpt_sp, 690 ConstString(name_to_remove)); 691 } 692 } 693 694 bool SBBreakpoint::MatchesName(const char *name) { 695 LLDB_INSTRUMENT_VA(this, name); 696 697 BreakpointSP bkpt_sp = GetSP(); 698 699 if (bkpt_sp) { 700 std::lock_guard<std::recursive_mutex> guard( 701 bkpt_sp->GetTarget().GetAPIMutex()); 702 return bkpt_sp->MatchesName(name); 703 } 704 705 return false; 706 } 707 708 void SBBreakpoint::GetNames(SBStringList &names) { 709 LLDB_INSTRUMENT_VA(this, names); 710 711 BreakpointSP bkpt_sp = GetSP(); 712 713 if (bkpt_sp) { 714 std::lock_guard<std::recursive_mutex> guard( 715 bkpt_sp->GetTarget().GetAPIMutex()); 716 std::vector<std::string> names_vec; 717 bkpt_sp->GetNames(names_vec); 718 for (std::string name : names_vec) { 719 names.AppendString(name.c_str()); 720 } 721 } 722 } 723 724 bool SBBreakpoint::EventIsBreakpointEvent(const lldb::SBEvent &event) { 725 LLDB_INSTRUMENT_VA(event); 726 727 return Breakpoint::BreakpointEventData::GetEventDataFromEvent(event.get()) != 728 nullptr; 729 } 730 731 BreakpointEventType 732 SBBreakpoint::GetBreakpointEventTypeFromEvent(const SBEvent &event) { 733 LLDB_INSTRUMENT_VA(event); 734 735 if (event.IsValid()) 736 return Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent( 737 event.GetSP()); 738 return eBreakpointEventTypeInvalidType; 739 } 740 741 SBBreakpoint SBBreakpoint::GetBreakpointFromEvent(const lldb::SBEvent &event) { 742 LLDB_INSTRUMENT_VA(event); 743 744 if (event.IsValid()) 745 return SBBreakpoint( 746 Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event.GetSP())); 747 return SBBreakpoint(); 748 } 749 750 SBBreakpointLocation 751 SBBreakpoint::GetBreakpointLocationAtIndexFromEvent(const lldb::SBEvent &event, 752 uint32_t loc_idx) { 753 LLDB_INSTRUMENT_VA(event, loc_idx); 754 755 SBBreakpointLocation sb_breakpoint_loc; 756 if (event.IsValid()) 757 sb_breakpoint_loc.SetLocation( 758 Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent( 759 event.GetSP(), loc_idx)); 760 return sb_breakpoint_loc; 761 } 762 763 uint32_t 764 SBBreakpoint::GetNumBreakpointLocationsFromEvent(const lldb::SBEvent &event) { 765 LLDB_INSTRUMENT_VA(event); 766 767 uint32_t num_locations = 0; 768 if (event.IsValid()) 769 num_locations = 770 (Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent( 771 event.GetSP())); 772 return num_locations; 773 } 774 775 bool SBBreakpoint::IsHardware() const { 776 LLDB_INSTRUMENT_VA(this); 777 778 BreakpointSP bkpt_sp = GetSP(); 779 if (bkpt_sp) 780 return bkpt_sp->IsHardware(); 781 return false; 782 } 783 784 BreakpointSP SBBreakpoint::GetSP() const { return m_opaque_wp.lock(); } 785 786 // This is simple collection of breakpoint id's and their target. 787 class SBBreakpointListImpl { 788 public: 789 SBBreakpointListImpl(lldb::TargetSP target_sp) { 790 if (target_sp && target_sp->IsValid()) 791 m_target_wp = target_sp; 792 } 793 794 ~SBBreakpointListImpl() = default; 795 796 size_t GetSize() { return m_break_ids.size(); } 797 798 BreakpointSP GetBreakpointAtIndex(size_t idx) { 799 if (idx >= m_break_ids.size()) 800 return BreakpointSP(); 801 TargetSP target_sp = m_target_wp.lock(); 802 if (!target_sp) 803 return BreakpointSP(); 804 lldb::break_id_t bp_id = m_break_ids[idx]; 805 return target_sp->GetBreakpointList().FindBreakpointByID(bp_id); 806 } 807 808 BreakpointSP FindBreakpointByID(lldb::break_id_t desired_id) { 809 TargetSP target_sp = m_target_wp.lock(); 810 if (!target_sp) 811 return BreakpointSP(); 812 813 for (lldb::break_id_t &break_id : m_break_ids) { 814 if (break_id == desired_id) 815 return target_sp->GetBreakpointList().FindBreakpointByID(break_id); 816 } 817 return BreakpointSP(); 818 } 819 820 bool Append(BreakpointSP bkpt) { 821 TargetSP target_sp = m_target_wp.lock(); 822 if (!target_sp || !bkpt) 823 return false; 824 if (bkpt->GetTargetSP() != target_sp) 825 return false; 826 m_break_ids.push_back(bkpt->GetID()); 827 return true; 828 } 829 830 bool AppendIfUnique(BreakpointSP bkpt) { 831 TargetSP target_sp = m_target_wp.lock(); 832 if (!target_sp || !bkpt) 833 return false; 834 if (bkpt->GetTargetSP() != target_sp) 835 return false; 836 lldb::break_id_t bp_id = bkpt->GetID(); 837 if (!llvm::is_contained(m_break_ids, bp_id)) 838 return false; 839 840 m_break_ids.push_back(bkpt->GetID()); 841 return true; 842 } 843 844 bool AppendByID(lldb::break_id_t id) { 845 TargetSP target_sp = m_target_wp.lock(); 846 if (!target_sp) 847 return false; 848 if (id == LLDB_INVALID_BREAK_ID) 849 return false; 850 m_break_ids.push_back(id); 851 return true; 852 } 853 854 void Clear() { m_break_ids.clear(); } 855 856 void CopyToBreakpointIDList(lldb_private::BreakpointIDList &bp_list) { 857 for (lldb::break_id_t id : m_break_ids) { 858 bp_list.AddBreakpointID(BreakpointID(id)); 859 } 860 } 861 862 TargetSP GetTarget() { return m_target_wp.lock(); } 863 864 private: 865 std::vector<lldb::break_id_t> m_break_ids; 866 TargetWP m_target_wp; 867 }; 868 869 SBBreakpointList::SBBreakpointList(SBTarget &target) 870 : m_opaque_sp(new SBBreakpointListImpl(target.GetSP())) { 871 LLDB_INSTRUMENT_VA(this, target); 872 } 873 874 SBBreakpointList::~SBBreakpointList() = default; 875 876 size_t SBBreakpointList::GetSize() const { 877 LLDB_INSTRUMENT_VA(this); 878 879 if (!m_opaque_sp) 880 return 0; 881 else 882 return m_opaque_sp->GetSize(); 883 } 884 885 SBBreakpoint SBBreakpointList::GetBreakpointAtIndex(size_t idx) { 886 LLDB_INSTRUMENT_VA(this, idx); 887 888 if (!m_opaque_sp) 889 return SBBreakpoint(); 890 891 BreakpointSP bkpt_sp = m_opaque_sp->GetBreakpointAtIndex(idx); 892 return SBBreakpoint(bkpt_sp); 893 } 894 895 SBBreakpoint SBBreakpointList::FindBreakpointByID(lldb::break_id_t id) { 896 LLDB_INSTRUMENT_VA(this, id); 897 898 if (!m_opaque_sp) 899 return SBBreakpoint(); 900 BreakpointSP bkpt_sp = m_opaque_sp->FindBreakpointByID(id); 901 return SBBreakpoint(bkpt_sp); 902 } 903 904 void SBBreakpointList::Append(const SBBreakpoint &sb_bkpt) { 905 LLDB_INSTRUMENT_VA(this, sb_bkpt); 906 907 if (!sb_bkpt.IsValid()) 908 return; 909 if (!m_opaque_sp) 910 return; 911 m_opaque_sp->Append(sb_bkpt.m_opaque_wp.lock()); 912 } 913 914 void SBBreakpointList::AppendByID(lldb::break_id_t id) { 915 LLDB_INSTRUMENT_VA(this, id); 916 917 if (!m_opaque_sp) 918 return; 919 m_opaque_sp->AppendByID(id); 920 } 921 922 bool SBBreakpointList::AppendIfUnique(const SBBreakpoint &sb_bkpt) { 923 LLDB_INSTRUMENT_VA(this, sb_bkpt); 924 925 if (!sb_bkpt.IsValid()) 926 return false; 927 if (!m_opaque_sp) 928 return false; 929 return m_opaque_sp->AppendIfUnique(sb_bkpt.GetSP()); 930 } 931 932 void SBBreakpointList::Clear() { 933 LLDB_INSTRUMENT_VA(this); 934 935 if (m_opaque_sp) 936 m_opaque_sp->Clear(); 937 } 938 939 void SBBreakpointList::CopyToBreakpointIDList( 940 lldb_private::BreakpointIDList &bp_id_list) { 941 if (m_opaque_sp) 942 m_opaque_sp->CopyToBreakpointIDList(bp_id_list); 943 } 944