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