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 uint32_t SBBreakpoint::GetHitCount() const { 268 uint32_t count = 0; 269 BreakpointSP bkpt_sp = GetSP(); 270 if (bkpt_sp) { 271 std::lock_guard<std::recursive_mutex> guard( 272 bkpt_sp->GetTarget().GetAPIMutex()); 273 count = bkpt_sp->GetHitCount(); 274 } 275 276 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 277 LLDB_LOG(log, "breakpoint = {0}, count = {1}", bkpt_sp.get(), count); 278 279 return count; 280 } 281 282 uint32_t SBBreakpoint::GetIgnoreCount() const { 283 uint32_t count = 0; 284 BreakpointSP bkpt_sp = GetSP(); 285 if (bkpt_sp) { 286 std::lock_guard<std::recursive_mutex> guard( 287 bkpt_sp->GetTarget().GetAPIMutex()); 288 count = bkpt_sp->GetIgnoreCount(); 289 } 290 291 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 292 LLDB_LOG(log, "breakpoint = {0}, count = {1}", bkpt_sp.get(), count); 293 294 return count; 295 } 296 297 void SBBreakpoint::SetThreadID(tid_t tid) { 298 BreakpointSP bkpt_sp = GetSP(); 299 if (bkpt_sp) { 300 std::lock_guard<std::recursive_mutex> guard( 301 bkpt_sp->GetTarget().GetAPIMutex()); 302 bkpt_sp->SetThreadID(tid); 303 } 304 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 305 LLDB_LOG(log, "breakpoint = {0}, tid = {1:x}", bkpt_sp.get(), tid); 306 } 307 308 tid_t SBBreakpoint::GetThreadID() { 309 tid_t tid = LLDB_INVALID_THREAD_ID; 310 BreakpointSP bkpt_sp = GetSP(); 311 if (bkpt_sp) { 312 std::lock_guard<std::recursive_mutex> guard( 313 bkpt_sp->GetTarget().GetAPIMutex()); 314 tid = bkpt_sp->GetThreadID(); 315 } 316 317 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 318 LLDB_LOG(log, "breakpoint = {0}, tid = {1:x}", bkpt_sp.get(), tid); 319 return tid; 320 } 321 322 void SBBreakpoint::SetThreadIndex(uint32_t index) { 323 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 324 BreakpointSP bkpt_sp = GetSP(); 325 LLDB_LOG(log, "breakpoint = {0}, index = {1}", bkpt_sp.get(), index); 326 if (bkpt_sp) { 327 std::lock_guard<std::recursive_mutex> guard( 328 bkpt_sp->GetTarget().GetAPIMutex()); 329 bkpt_sp->GetOptions()->GetThreadSpec()->SetIndex(index); 330 } 331 } 332 333 uint32_t SBBreakpoint::GetThreadIndex() const { 334 uint32_t thread_idx = UINT32_MAX; 335 BreakpointSP bkpt_sp = GetSP(); 336 if (bkpt_sp) { 337 std::lock_guard<std::recursive_mutex> guard( 338 bkpt_sp->GetTarget().GetAPIMutex()); 339 const ThreadSpec *thread_spec = 340 bkpt_sp->GetOptions()->GetThreadSpecNoCreate(); 341 if (thread_spec != nullptr) 342 thread_idx = thread_spec->GetIndex(); 343 } 344 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 345 LLDB_LOG(log, "breakpoint = {0}, index = {1}", bkpt_sp.get(), thread_idx); 346 347 return thread_idx; 348 } 349 350 void SBBreakpoint::SetThreadName(const char *thread_name) { 351 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 352 BreakpointSP bkpt_sp = GetSP(); 353 LLDB_LOG(log, "breakpoint = {0}, name = {1}", bkpt_sp.get(), thread_name); 354 355 if (bkpt_sp) { 356 std::lock_guard<std::recursive_mutex> guard( 357 bkpt_sp->GetTarget().GetAPIMutex()); 358 bkpt_sp->GetOptions()->GetThreadSpec()->SetName(thread_name); 359 } 360 } 361 362 const char *SBBreakpoint::GetThreadName() const { 363 const char *name = nullptr; 364 BreakpointSP bkpt_sp = GetSP(); 365 if (bkpt_sp) { 366 std::lock_guard<std::recursive_mutex> guard( 367 bkpt_sp->GetTarget().GetAPIMutex()); 368 const ThreadSpec *thread_spec = 369 bkpt_sp->GetOptions()->GetThreadSpecNoCreate(); 370 if (thread_spec != nullptr) 371 name = thread_spec->GetName(); 372 } 373 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 374 LLDB_LOG(log, "breakpoint = {0}, name = {1}", bkpt_sp.get(), name); 375 376 return name; 377 } 378 379 void SBBreakpoint::SetQueueName(const char *queue_name) { 380 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 381 BreakpointSP bkpt_sp = GetSP(); 382 LLDB_LOG(log, "breakpoint = {0}, queue_name = {1}", bkpt_sp.get(), 383 queue_name); 384 if (bkpt_sp) { 385 std::lock_guard<std::recursive_mutex> guard( 386 bkpt_sp->GetTarget().GetAPIMutex()); 387 bkpt_sp->GetOptions()->GetThreadSpec()->SetQueueName(queue_name); 388 } 389 } 390 391 const char *SBBreakpoint::GetQueueName() const { 392 const char *name = nullptr; 393 BreakpointSP bkpt_sp = GetSP(); 394 if (bkpt_sp) { 395 std::lock_guard<std::recursive_mutex> guard( 396 bkpt_sp->GetTarget().GetAPIMutex()); 397 const ThreadSpec *thread_spec = 398 bkpt_sp->GetOptions()->GetThreadSpecNoCreate(); 399 if (thread_spec) 400 name = thread_spec->GetQueueName(); 401 } 402 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 403 LLDB_LOG(log, "breakpoint = {0}, name = {1}", bkpt_sp.get(), name); 404 405 return name; 406 } 407 408 size_t SBBreakpoint::GetNumResolvedLocations() const { 409 size_t num_resolved = 0; 410 BreakpointSP bkpt_sp = GetSP(); 411 if (bkpt_sp) { 412 std::lock_guard<std::recursive_mutex> guard( 413 bkpt_sp->GetTarget().GetAPIMutex()); 414 num_resolved = bkpt_sp->GetNumResolvedLocations(); 415 } 416 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 417 LLDB_LOG(log, "breakpoint = {0}, num_resolved = {1}", bkpt_sp.get(), 418 num_resolved); 419 return num_resolved; 420 } 421 422 size_t SBBreakpoint::GetNumLocations() const { 423 BreakpointSP bkpt_sp = GetSP(); 424 size_t num_locs = 0; 425 if (bkpt_sp) { 426 std::lock_guard<std::recursive_mutex> guard( 427 bkpt_sp->GetTarget().GetAPIMutex()); 428 num_locs = bkpt_sp->GetNumLocations(); 429 } 430 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 431 LLDB_LOG(log, "breakpoint = {0}, num_locs = {1}", bkpt_sp.get(), num_locs); 432 return num_locs; 433 } 434 435 void SBBreakpoint::SetCommandLineCommands(SBStringList &commands) { 436 BreakpointSP bkpt_sp = GetSP(); 437 if (!bkpt_sp) 438 return; 439 if (commands.GetSize() == 0) 440 return; 441 442 std::lock_guard<std::recursive_mutex> guard( 443 bkpt_sp->GetTarget().GetAPIMutex()); 444 std::unique_ptr<BreakpointOptions::CommandData> cmd_data_up( 445 new BreakpointOptions::CommandData(*commands, eScriptLanguageNone)); 446 447 bkpt_sp->GetOptions()->SetCommandDataCallback(cmd_data_up); 448 } 449 450 bool SBBreakpoint::GetCommandLineCommands(SBStringList &commands) { 451 BreakpointSP bkpt_sp = GetSP(); 452 if (!bkpt_sp) 453 return false; 454 StringList command_list; 455 bool has_commands = 456 bkpt_sp->GetOptions()->GetCommandLineCallbacks(command_list); 457 if (has_commands) 458 commands.AppendList(command_list); 459 return has_commands; 460 } 461 462 bool SBBreakpoint::GetDescription(SBStream &s) { 463 return GetDescription(s, true); 464 } 465 466 bool SBBreakpoint::GetDescription(SBStream &s, bool include_locations) { 467 BreakpointSP bkpt_sp = GetSP(); 468 if (bkpt_sp) { 469 std::lock_guard<std::recursive_mutex> guard( 470 bkpt_sp->GetTarget().GetAPIMutex()); 471 s.Printf("SBBreakpoint: id = %i, ", bkpt_sp->GetID()); 472 bkpt_sp->GetResolverDescription(s.get()); 473 bkpt_sp->GetFilterDescription(s.get()); 474 if (include_locations) { 475 const size_t num_locations = bkpt_sp->GetNumLocations(); 476 s.Printf(", locations = %" PRIu64, (uint64_t)num_locations); 477 } 478 return true; 479 } 480 s.Printf("No value"); 481 return false; 482 } 483 484 bool SBBreakpoint::PrivateBreakpointHitCallback(void *baton, 485 StoppointCallbackContext *ctx, 486 lldb::user_id_t break_id, 487 lldb::user_id_t break_loc_id) { 488 ExecutionContext exe_ctx(ctx->exe_ctx_ref); 489 BreakpointSP bp_sp( 490 exe_ctx.GetTargetRef().GetBreakpointList().FindBreakpointByID(break_id)); 491 if (baton && bp_sp) { 492 CallbackData *data = (CallbackData *)baton; 493 lldb_private::Breakpoint *bp = bp_sp.get(); 494 if (bp && data->callback) { 495 Process *process = exe_ctx.GetProcessPtr(); 496 if (process) { 497 SBProcess sb_process(process->shared_from_this()); 498 SBThread sb_thread; 499 SBBreakpointLocation sb_location; 500 assert(bp_sp); 501 sb_location.SetLocation(bp_sp->FindLocationByID(break_loc_id)); 502 Thread *thread = exe_ctx.GetThreadPtr(); 503 if (thread) 504 sb_thread.SetThread(thread->shared_from_this()); 505 506 return data->callback(data->callback_baton, sb_process, sb_thread, 507 sb_location); 508 } 509 } 510 } 511 return true; // Return true if we should stop at this breakpoint 512 } 513 514 void SBBreakpoint::SetCallback(BreakpointHitCallback callback, void *baton) { 515 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 516 BreakpointSP bkpt_sp = GetSP(); 517 LLDB_LOG(log, "breakpoint = {0}, callback = {1}, baton = {2}", bkpt_sp.get(), 518 callback, baton); 519 520 if (bkpt_sp) { 521 std::lock_guard<std::recursive_mutex> guard( 522 bkpt_sp->GetTarget().GetAPIMutex()); 523 BatonSP baton_sp(new SBBreakpointCallbackBaton(callback, baton)); 524 bkpt_sp->SetCallback(SBBreakpoint::PrivateBreakpointHitCallback, baton_sp, 525 false); 526 } 527 } 528 529 void SBBreakpoint::SetScriptCallbackFunction( 530 const char *callback_function_name) { 531 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 532 BreakpointSP bkpt_sp = GetSP(); 533 LLDB_LOG(log, "breakpoint = {0}, callback = {1}", bkpt_sp.get(), 534 callback_function_name); 535 536 if (bkpt_sp) { 537 std::lock_guard<std::recursive_mutex> guard( 538 bkpt_sp->GetTarget().GetAPIMutex()); 539 BreakpointOptions *bp_options = bkpt_sp->GetOptions(); 540 bkpt_sp->GetTarget() 541 .GetDebugger() 542 .GetCommandInterpreter() 543 .GetScriptInterpreter() 544 ->SetBreakpointCommandCallbackFunction(bp_options, 545 callback_function_name); 546 } 547 } 548 549 SBError SBBreakpoint::SetScriptCallbackBody(const char *callback_body_text) { 550 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 551 BreakpointSP bkpt_sp = GetSP(); 552 LLDB_LOG(log, "breakpoint = {0}, callback body:\n{1}", bkpt_sp.get(), 553 callback_body_text); 554 555 SBError sb_error; 556 if (bkpt_sp) { 557 std::lock_guard<std::recursive_mutex> guard( 558 bkpt_sp->GetTarget().GetAPIMutex()); 559 BreakpointOptions *bp_options = bkpt_sp->GetOptions(); 560 Error error = 561 bkpt_sp->GetTarget() 562 .GetDebugger() 563 .GetCommandInterpreter() 564 .GetScriptInterpreter() 565 ->SetBreakpointCommandCallback(bp_options, callback_body_text); 566 sb_error.SetError(error); 567 } else 568 sb_error.SetErrorString("invalid breakpoint"); 569 570 return sb_error; 571 } 572 573 bool SBBreakpoint::AddName(const char *new_name) { 574 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 575 BreakpointSP bkpt_sp = GetSP(); 576 LLDB_LOG(log, "breakpoint = {0}, name = {1}", bkpt_sp.get(), new_name); 577 578 if (bkpt_sp) { 579 std::lock_guard<std::recursive_mutex> guard( 580 bkpt_sp->GetTarget().GetAPIMutex()); 581 Error error; // Think I'm just going to swallow the error here, it's 582 // probably more annoying to have to provide it. 583 return bkpt_sp->AddName(new_name, error); 584 } 585 586 return false; 587 } 588 589 void SBBreakpoint::RemoveName(const char *name_to_remove) { 590 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 591 BreakpointSP bkpt_sp = GetSP(); 592 LLDB_LOG(log, "breakpoint = {0}, name = {1}", bkpt_sp.get(), name_to_remove); 593 594 if (bkpt_sp) { 595 std::lock_guard<std::recursive_mutex> guard( 596 bkpt_sp->GetTarget().GetAPIMutex()); 597 bkpt_sp->RemoveName(name_to_remove); 598 } 599 } 600 601 bool SBBreakpoint::MatchesName(const char *name) { 602 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 603 BreakpointSP bkpt_sp = GetSP(); 604 LLDB_LOG(log, "breakpoint = {0}, name = {1}", bkpt_sp.get(), name); 605 606 if (bkpt_sp) { 607 std::lock_guard<std::recursive_mutex> guard( 608 bkpt_sp->GetTarget().GetAPIMutex()); 609 return bkpt_sp->MatchesName(name); 610 } 611 612 return false; 613 } 614 615 void SBBreakpoint::GetNames(SBStringList &names) { 616 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 617 BreakpointSP bkpt_sp = GetSP(); 618 LLDB_LOG(log, "breakpoint = {0}", bkpt_sp.get()); 619 620 if (bkpt_sp) { 621 std::lock_guard<std::recursive_mutex> guard( 622 bkpt_sp->GetTarget().GetAPIMutex()); 623 std::vector<std::string> names_vec; 624 bkpt_sp->GetNames(names_vec); 625 for (std::string name : names_vec) { 626 names.AppendString(name.c_str()); 627 } 628 } 629 } 630 631 bool SBBreakpoint::EventIsBreakpointEvent(const lldb::SBEvent &event) { 632 return Breakpoint::BreakpointEventData::GetEventDataFromEvent(event.get()) != 633 nullptr; 634 } 635 636 BreakpointEventType 637 SBBreakpoint::GetBreakpointEventTypeFromEvent(const SBEvent &event) { 638 if (event.IsValid()) 639 return Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent( 640 event.GetSP()); 641 return eBreakpointEventTypeInvalidType; 642 } 643 644 SBBreakpoint SBBreakpoint::GetBreakpointFromEvent(const lldb::SBEvent &event) { 645 if (event.IsValid()) 646 return SBBreakpoint( 647 Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event.GetSP())); 648 return SBBreakpoint(); 649 } 650 651 SBBreakpointLocation 652 SBBreakpoint::GetBreakpointLocationAtIndexFromEvent(const lldb::SBEvent &event, 653 uint32_t loc_idx) { 654 SBBreakpointLocation sb_breakpoint_loc; 655 if (event.IsValid()) 656 sb_breakpoint_loc.SetLocation( 657 Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent( 658 event.GetSP(), loc_idx)); 659 return sb_breakpoint_loc; 660 } 661 662 uint32_t 663 SBBreakpoint::GetNumBreakpointLocationsFromEvent(const lldb::SBEvent &event) { 664 uint32_t num_locations = 0; 665 if (event.IsValid()) 666 num_locations = 667 (Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent( 668 event.GetSP())); 669 return num_locations; 670 } 671 672 BreakpointSP SBBreakpoint::GetSP() const { return m_opaque_wp.lock(); } 673 674 // This is simple collection of breakpoint id's and their target. 675 class SBBreakpointListImpl { 676 public: 677 SBBreakpointListImpl(lldb::TargetSP target_sp) : m_target_wp() { 678 if (target_sp && target_sp->IsValid()) 679 m_target_wp = target_sp; 680 } 681 682 ~SBBreakpointListImpl() = default; 683 684 size_t GetSize() { return m_break_ids.size(); } 685 686 BreakpointSP GetBreakpointAtIndex(size_t idx) { 687 if (idx >= m_break_ids.size()) 688 return BreakpointSP(); 689 TargetSP target_sp = m_target_wp.lock(); 690 if (!target_sp) 691 return BreakpointSP(); 692 lldb::break_id_t bp_id = m_break_ids[idx]; 693 return target_sp->GetBreakpointList().FindBreakpointByID(bp_id); 694 } 695 696 BreakpointSP FindBreakpointByID(lldb::break_id_t desired_id) { 697 TargetSP target_sp = m_target_wp.lock(); 698 if (!target_sp) 699 return BreakpointSP(); 700 701 for (lldb::break_id_t &break_id : m_break_ids) { 702 if (break_id == desired_id) 703 return target_sp->GetBreakpointList().FindBreakpointByID(break_id); 704 } 705 return BreakpointSP(); 706 } 707 708 bool Append(BreakpointSP bkpt) { 709 TargetSP target_sp = m_target_wp.lock(); 710 if (!target_sp || !bkpt) 711 return false; 712 if (bkpt->GetTargetSP() != target_sp) 713 return false; 714 m_break_ids.push_back(bkpt->GetID()); 715 return true; 716 } 717 718 bool AppendIfUnique(BreakpointSP bkpt) { 719 TargetSP target_sp = m_target_wp.lock(); 720 if (!target_sp || !bkpt) 721 return false; 722 if (bkpt->GetTargetSP() != target_sp) 723 return false; 724 lldb::break_id_t bp_id = bkpt->GetID(); 725 if (find(m_break_ids.begin(), m_break_ids.end(), bp_id) == 726 m_break_ids.end()) 727 return false; 728 729 m_break_ids.push_back(bkpt->GetID()); 730 return true; 731 } 732 733 bool AppendByID(lldb::break_id_t id) { 734 TargetSP target_sp = m_target_wp.lock(); 735 if (!target_sp) 736 return false; 737 if (id == LLDB_INVALID_BREAK_ID) 738 return false; 739 m_break_ids.push_back(id); 740 return true; 741 } 742 743 void Clear() { m_break_ids.clear(); } 744 745 void CopyToBreakpointIDList(lldb_private::BreakpointIDList &bp_list) { 746 for (lldb::break_id_t id : m_break_ids) { 747 bp_list.AddBreakpointID(BreakpointID(id)); 748 } 749 } 750 751 TargetSP GetTarget() { return m_target_wp.lock(); } 752 753 private: 754 std::vector<lldb::break_id_t> m_break_ids; 755 TargetWP m_target_wp; 756 }; 757 758 SBBreakpointList::SBBreakpointList(SBTarget &target) 759 : m_opaque_sp(new SBBreakpointListImpl(target.GetSP())) {} 760 761 SBBreakpointList::~SBBreakpointList() {} 762 763 size_t SBBreakpointList::GetSize() const { 764 if (!m_opaque_sp) 765 return 0; 766 else 767 return m_opaque_sp->GetSize(); 768 } 769 770 SBBreakpoint SBBreakpointList::GetBreakpointAtIndex(size_t idx) { 771 if (!m_opaque_sp) 772 return SBBreakpoint(); 773 774 BreakpointSP bkpt_sp = m_opaque_sp->GetBreakpointAtIndex(idx); 775 return SBBreakpoint(bkpt_sp); 776 } 777 778 SBBreakpoint SBBreakpointList::FindBreakpointByID(lldb::break_id_t id) { 779 if (!m_opaque_sp) 780 return SBBreakpoint(); 781 BreakpointSP bkpt_sp = m_opaque_sp->FindBreakpointByID(id); 782 return SBBreakpoint(bkpt_sp); 783 } 784 785 void SBBreakpointList::Append(const SBBreakpoint &sb_bkpt) { 786 if (!sb_bkpt.IsValid()) 787 return; 788 if (!m_opaque_sp) 789 return; 790 m_opaque_sp->Append(sb_bkpt.m_opaque_wp.lock()); 791 } 792 793 void SBBreakpointList::AppendByID(lldb::break_id_t id) { 794 if (!m_opaque_sp) 795 return; 796 m_opaque_sp->AppendByID(id); 797 } 798 799 bool SBBreakpointList::AppendIfUnique(const SBBreakpoint &sb_bkpt) { 800 if (!sb_bkpt.IsValid()) 801 return false; 802 if (!m_opaque_sp) 803 return false; 804 return m_opaque_sp->AppendIfUnique(sb_bkpt.GetSP()); 805 } 806 807 void SBBreakpointList::Clear() { 808 if (m_opaque_sp) 809 m_opaque_sp->Clear(); 810 } 811 812 void SBBreakpointList::CopyToBreakpointIDList( 813 lldb_private::BreakpointIDList &bp_id_list) { 814 if (m_opaque_sp) 815 m_opaque_sp->CopyToBreakpointIDList(bp_id_list); 816 } 817