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.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.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(lldb::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 lldb::tid_t SBBreakpoint::GetThreadID() { 357 LLDB_INSTRUMENT_VA(this); 358 359 lldb::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 = Status::FromErrorString("Can't add an invalid address."); 544 return error; 545 } 546 547 if (!bkpt_sp) { 548 error = Status::FromErrorString("No breakpoint to add a location to."); 549 return error; 550 } 551 552 if (!llvm::isa<BreakpointResolverScripted>(bkpt_sp->GetResolver().get())) { 553 error = 554 Status::FromErrorString("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 = Status::FromErrorStringWithFormat( 565 "Address: %s didn't pass the filter.", 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(std::move(error)); 626 } else 627 sb_error = Status::FromErrorString("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(std::move(error)); 649 } else 650 sb_error = Status::FromErrorString("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(std::move(error)); 674 } else { 675 status = Status::FromErrorString("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 (const 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