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