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