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