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