1 //===-- BreakpointLocation.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/Breakpoint/BreakpointLocation.h" 15 #include "lldb/Breakpoint/BreakpointID.h" 16 #include "lldb/Breakpoint/StoppointCallbackContext.h" 17 #include "lldb/Core/Debugger.h" 18 #include "lldb/Core/Log.h" 19 #include "lldb/Core/Module.h" 20 #include "lldb/Core/StreamString.h" 21 #include "lldb/Core/ValueObject.h" 22 #include "lldb/Expression/DiagnosticManager.h" 23 #include "lldb/Expression/ExpressionVariable.h" 24 #include "lldb/Expression/UserExpression.h" 25 #include "lldb/Symbol/CompileUnit.h" 26 #include "lldb/Symbol/Symbol.h" 27 #include "lldb/Symbol/TypeSystem.h" 28 #include "lldb/Target/Target.h" 29 #include "lldb/Target/Process.h" 30 #include "lldb/Target/Thread.h" 31 #include "lldb/Target/ThreadSpec.h" 32 33 using namespace lldb; 34 using namespace lldb_private; 35 36 BreakpointLocation::BreakpointLocation 37 ( 38 break_id_t loc_id, 39 Breakpoint &owner, 40 const Address &addr, 41 lldb::tid_t tid, 42 bool hardware, 43 bool check_for_resolver 44 ) : 45 StoppointLocation (loc_id, addr.GetOpcodeLoadAddress(&owner.GetTarget()), hardware), 46 m_being_created(true), 47 m_should_resolve_indirect_functions (false), 48 m_is_reexported (false), 49 m_is_indirect (false), 50 m_address (addr), 51 m_owner (owner), 52 m_options_ap (), 53 m_bp_site_sp (), 54 m_condition_mutex () 55 { 56 if (check_for_resolver) 57 { 58 Symbol *symbol = m_address.CalculateSymbolContextSymbol(); 59 if (symbol && symbol->IsIndirect()) 60 { 61 SetShouldResolveIndirectFunctions (true); 62 } 63 } 64 65 SetThreadID (tid); 66 m_being_created = false; 67 } 68 69 BreakpointLocation::~BreakpointLocation() 70 { 71 ClearBreakpointSite(); 72 } 73 74 lldb::addr_t 75 BreakpointLocation::GetLoadAddress () const 76 { 77 return m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()); 78 } 79 80 Address & 81 BreakpointLocation::GetAddress () 82 { 83 return m_address; 84 } 85 86 Breakpoint & 87 BreakpointLocation::GetBreakpoint () 88 { 89 return m_owner; 90 } 91 92 Target & 93 BreakpointLocation::GetTarget() 94 { 95 return m_owner.GetTarget(); 96 } 97 98 bool 99 BreakpointLocation::IsEnabled () const 100 { 101 if (!m_owner.IsEnabled()) 102 return false; 103 else if (m_options_ap.get() != nullptr) 104 return m_options_ap->IsEnabled(); 105 else 106 return true; 107 } 108 109 void 110 BreakpointLocation::SetEnabled (bool enabled) 111 { 112 GetLocationOptions()->SetEnabled(enabled); 113 if (enabled) 114 { 115 ResolveBreakpointSite(); 116 } 117 else 118 { 119 ClearBreakpointSite(); 120 } 121 SendBreakpointLocationChangedEvent (enabled ? eBreakpointEventTypeEnabled : eBreakpointEventTypeDisabled); 122 } 123 124 void 125 BreakpointLocation::SetThreadID (lldb::tid_t thread_id) 126 { 127 if (thread_id != LLDB_INVALID_THREAD_ID) 128 GetLocationOptions()->SetThreadID(thread_id); 129 else 130 { 131 // If we're resetting this to an invalid thread id, then 132 // don't make an options pointer just to do that. 133 if (m_options_ap.get() != nullptr) 134 m_options_ap->SetThreadID (thread_id); 135 } 136 SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged); 137 } 138 139 lldb::tid_t 140 BreakpointLocation::GetThreadID () 141 { 142 if (GetOptionsNoCreate()->GetThreadSpecNoCreate()) 143 return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(); 144 else 145 return LLDB_INVALID_THREAD_ID; 146 } 147 148 void 149 BreakpointLocation::SetThreadIndex (uint32_t index) 150 { 151 if (index != 0) 152 GetLocationOptions()->GetThreadSpec()->SetIndex(index); 153 else 154 { 155 // If we're resetting this to an invalid thread id, then 156 // don't make an options pointer just to do that. 157 if (m_options_ap.get() != nullptr) 158 m_options_ap->GetThreadSpec()->SetIndex(index); 159 } 160 SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged); 161 } 162 163 uint32_t 164 BreakpointLocation::GetThreadIndex() const 165 { 166 if (GetOptionsNoCreate()->GetThreadSpecNoCreate()) 167 return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetIndex(); 168 else 169 return 0; 170 } 171 172 void 173 BreakpointLocation::SetThreadName (const char *thread_name) 174 { 175 if (thread_name != nullptr) 176 GetLocationOptions()->GetThreadSpec()->SetName(thread_name); 177 else 178 { 179 // If we're resetting this to an invalid thread id, then 180 // don't make an options pointer just to do that. 181 if (m_options_ap.get() != nullptr) 182 m_options_ap->GetThreadSpec()->SetName(thread_name); 183 } 184 SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged); 185 } 186 187 const char * 188 BreakpointLocation::GetThreadName () const 189 { 190 if (GetOptionsNoCreate()->GetThreadSpecNoCreate()) 191 return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetName(); 192 else 193 return nullptr; 194 } 195 196 void 197 BreakpointLocation::SetQueueName (const char *queue_name) 198 { 199 if (queue_name != nullptr) 200 GetLocationOptions()->GetThreadSpec()->SetQueueName(queue_name); 201 else 202 { 203 // If we're resetting this to an invalid thread id, then 204 // don't make an options pointer just to do that. 205 if (m_options_ap.get() != nullptr) 206 m_options_ap->GetThreadSpec()->SetQueueName(queue_name); 207 } 208 SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged); 209 } 210 211 const char * 212 BreakpointLocation::GetQueueName () const 213 { 214 if (GetOptionsNoCreate()->GetThreadSpecNoCreate()) 215 return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetQueueName(); 216 else 217 return nullptr; 218 } 219 220 bool 221 BreakpointLocation::InvokeCallback (StoppointCallbackContext *context) 222 { 223 if (m_options_ap.get() != nullptr && m_options_ap->HasCallback()) 224 return m_options_ap->InvokeCallback (context, m_owner.GetID(), GetID()); 225 else 226 return m_owner.InvokeCallback (context, GetID()); 227 } 228 229 void 230 BreakpointLocation::SetCallback (BreakpointHitCallback callback, void *baton, 231 bool is_synchronous) 232 { 233 // The default "Baton" class will keep a copy of "baton" and won't free 234 // or delete it when it goes goes out of scope. 235 GetLocationOptions()->SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous); 236 SendBreakpointLocationChangedEvent (eBreakpointEventTypeCommandChanged); 237 } 238 239 void 240 BreakpointLocation::SetCallback (BreakpointHitCallback callback, const BatonSP &baton_sp, 241 bool is_synchronous) 242 { 243 GetLocationOptions()->SetCallback (callback, baton_sp, is_synchronous); 244 SendBreakpointLocationChangedEvent (eBreakpointEventTypeCommandChanged); 245 } 246 247 void 248 BreakpointLocation::ClearCallback () 249 { 250 GetLocationOptions()->ClearCallback(); 251 } 252 253 void 254 BreakpointLocation::SetCondition (const char *condition) 255 { 256 GetLocationOptions()->SetCondition (condition); 257 SendBreakpointLocationChangedEvent (eBreakpointEventTypeConditionChanged); 258 } 259 260 const char * 261 BreakpointLocation::GetConditionText (size_t *hash) const 262 { 263 return GetOptionsNoCreate()->GetConditionText(hash); 264 } 265 266 bool 267 BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error) 268 { 269 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 270 271 Mutex::Locker evaluation_locker(m_condition_mutex); 272 273 size_t condition_hash; 274 const char *condition_text = GetConditionText(&condition_hash); 275 276 if (!condition_text) 277 { 278 m_user_expression_sp.reset(); 279 return false; 280 } 281 282 DiagnosticManager diagnostics; 283 284 if (condition_hash != m_condition_hash || !m_user_expression_sp || !m_user_expression_sp->MatchesContext(exe_ctx)) 285 { 286 LanguageType language = eLanguageTypeUnknown; 287 // See if we can figure out the language from the frame, otherwise use the default language: 288 CompileUnit *comp_unit = m_address.CalculateSymbolContextCompileUnit(); 289 if (comp_unit) 290 language = comp_unit->GetLanguage(); 291 292 Error error; 293 m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage(condition_text, 294 nullptr, 295 language, 296 Expression::eResultTypeAny, 297 EvaluateExpressionOptions(), 298 error)); 299 if (error.Fail()) 300 { 301 if (log) 302 log->Printf("Error getting condition expression: %s.", error.AsCString()); 303 m_user_expression_sp.reset(); 304 return true; 305 } 306 307 if (!m_user_expression_sp->Parse(diagnostics, exe_ctx, eExecutionPolicyOnlyWhenNeeded, true, false)) 308 { 309 error.SetErrorStringWithFormat("Couldn't parse conditional expression:\n%s", 310 diagnostics.GetString().c_str()); 311 m_user_expression_sp.reset(); 312 return false; 313 } 314 315 m_condition_hash = condition_hash; 316 } 317 318 // We need to make sure the user sees any parse errors in their condition, so we'll hook the 319 // constructor errors up to the debugger's Async I/O. 320 321 ValueObjectSP result_value_sp; 322 323 EvaluateExpressionOptions options; 324 options.SetUnwindOnError(true); 325 options.SetIgnoreBreakpoints(true); 326 options.SetTryAllThreads(true); 327 options.SetResultIsInternal(true); // Don't generate a user variable for condition expressions. 328 329 Error expr_error; 330 331 diagnostics.Clear(); 332 333 ExpressionVariableSP result_variable_sp; 334 335 ExpressionResults result_code = 336 m_user_expression_sp->Execute(diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp); 337 338 bool ret; 339 340 if (result_code == eExpressionCompleted) 341 { 342 if (!result_variable_sp) 343 { 344 error.SetErrorString("Expression did not return a result"); 345 return false; 346 } 347 348 result_value_sp = result_variable_sp->GetValueObject(); 349 350 if (result_value_sp) 351 { 352 ret = result_value_sp->IsLogicalTrue(error); 353 if (log) 354 { 355 if (error.Success()) 356 { 357 log->Printf("Condition successfully evaluated, result is %s.\n", 358 ret ? "true" : "false"); 359 } 360 else 361 { 362 error.SetErrorString("Failed to get an integer result from the expression"); 363 ret = false; 364 } 365 366 } 367 } 368 else 369 { 370 ret = false; 371 error.SetErrorString("Failed to get any result from the expression"); 372 } 373 } 374 else 375 { 376 ret = false; 377 error.SetErrorStringWithFormat("Couldn't execute expression:\n%s", diagnostics.GetString().c_str()); 378 } 379 380 return ret; 381 } 382 383 uint32_t 384 BreakpointLocation::GetIgnoreCount () 385 { 386 return GetOptionsNoCreate()->GetIgnoreCount(); 387 } 388 389 void 390 BreakpointLocation::SetIgnoreCount (uint32_t n) 391 { 392 GetLocationOptions()->SetIgnoreCount(n); 393 SendBreakpointLocationChangedEvent (eBreakpointEventTypeIgnoreChanged); 394 } 395 396 void 397 BreakpointLocation::DecrementIgnoreCount() 398 { 399 if (m_options_ap.get() != nullptr) 400 { 401 uint32_t loc_ignore = m_options_ap->GetIgnoreCount(); 402 if (loc_ignore != 0) 403 m_options_ap->SetIgnoreCount(loc_ignore - 1); 404 } 405 } 406 407 bool 408 BreakpointLocation::IgnoreCountShouldStop() 409 { 410 if (m_options_ap.get() != nullptr) 411 { 412 uint32_t loc_ignore = m_options_ap->GetIgnoreCount(); 413 if (loc_ignore != 0) 414 { 415 m_owner.DecrementIgnoreCount(); 416 DecrementIgnoreCount(); // Have to decrement our owners' ignore count, since it won't get a 417 // chance to. 418 return false; 419 } 420 } 421 return true; 422 } 423 424 const BreakpointOptions * 425 BreakpointLocation::GetOptionsNoCreate () const 426 { 427 if (m_options_ap.get() != nullptr) 428 return m_options_ap.get(); 429 else 430 return m_owner.GetOptions (); 431 } 432 433 BreakpointOptions * 434 BreakpointLocation::GetLocationOptions () 435 { 436 // If we make the copy we don't copy the callbacks because that is potentially 437 // expensive and we don't want to do that for the simple case where someone is 438 // just disabling the location. 439 if (m_options_ap.get() == nullptr) 440 m_options_ap.reset(BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions ())); 441 442 return m_options_ap.get(); 443 } 444 445 bool 446 BreakpointLocation::ValidForThisThread (Thread *thread) 447 { 448 return thread->MatchesSpec(GetOptionsNoCreate()->GetThreadSpecNoCreate()); 449 } 450 451 // RETURNS - true if we should stop at this breakpoint, false if we 452 // should continue. Note, we don't check the thread spec for the breakpoint 453 // here, since if the breakpoint is not for this thread, then the event won't 454 // even get reported, so the check is redundant. 455 456 bool 457 BreakpointLocation::ShouldStop (StoppointCallbackContext *context) 458 { 459 bool should_stop = true; 460 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 461 462 // Do this first, if a location is disabled, it shouldn't increment its hit count. 463 if (!IsEnabled()) 464 return false; 465 466 if (!IgnoreCountShouldStop()) 467 return false; 468 469 if (!m_owner.IgnoreCountShouldStop()) 470 return false; 471 472 // We only run synchronous callbacks in ShouldStop: 473 context->is_synchronous = true; 474 should_stop = InvokeCallback (context); 475 476 if (log) 477 { 478 StreamString s; 479 GetDescription (&s, lldb::eDescriptionLevelVerbose); 480 log->Printf ("Hit breakpoint location: %s, %s.\n", s.GetData(), should_stop ? "stopping" : "continuing"); 481 } 482 483 return should_stop; 484 } 485 486 void 487 BreakpointLocation::BumpHitCount() 488 { 489 if (IsEnabled()) 490 { 491 // Step our hit count, and also step the hit count of the owner. 492 IncrementHitCount(); 493 m_owner.IncrementHitCount(); 494 } 495 } 496 497 void 498 BreakpointLocation::UndoBumpHitCount() 499 { 500 if (IsEnabled()) 501 { 502 // Step our hit count, and also step the hit count of the owner. 503 DecrementHitCount(); 504 m_owner.DecrementHitCount(); 505 } 506 } 507 508 bool 509 BreakpointLocation::IsResolved () const 510 { 511 return m_bp_site_sp.get() != nullptr; 512 } 513 514 lldb::BreakpointSiteSP 515 BreakpointLocation::GetBreakpointSite() const 516 { 517 return m_bp_site_sp; 518 } 519 520 bool 521 BreakpointLocation::ResolveBreakpointSite () 522 { 523 if (m_bp_site_sp) 524 return true; 525 526 Process *process = m_owner.GetTarget().GetProcessSP().get(); 527 if (process == nullptr) 528 return false; 529 530 lldb::break_id_t new_id = process->CreateBreakpointSite (shared_from_this(), m_owner.IsHardware()); 531 532 if (new_id == LLDB_INVALID_BREAK_ID) 533 { 534 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 535 if (log) 536 log->Warning ("Tried to add breakpoint site at 0x%" PRIx64 " but it was already present.\n", 537 m_address.GetOpcodeLoadAddress (&m_owner.GetTarget())); 538 return false; 539 } 540 541 return true; 542 } 543 544 bool 545 BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp) 546 { 547 m_bp_site_sp = bp_site_sp; 548 SendBreakpointLocationChangedEvent (eBreakpointEventTypeLocationsResolved); 549 return true; 550 } 551 552 bool 553 BreakpointLocation::ClearBreakpointSite () 554 { 555 if (m_bp_site_sp.get()) 556 { 557 ProcessSP process_sp(m_owner.GetTarget().GetProcessSP()); 558 // If the process exists, get it to remove the owner, it will remove the physical implementation 559 // of the breakpoint as well if there are no more owners. Otherwise just remove this owner. 560 if (process_sp) 561 process_sp->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(), 562 GetID(), m_bp_site_sp); 563 else 564 m_bp_site_sp->RemoveOwner(GetBreakpoint().GetID(), GetID()); 565 566 m_bp_site_sp.reset(); 567 return true; 568 } 569 return false; 570 } 571 572 void 573 BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level) 574 { 575 SymbolContext sc; 576 577 // If the description level is "initial" then the breakpoint is printing out our initial state, 578 // and we should let it decide how it wants to print our label. 579 if (level != eDescriptionLevelInitial) 580 { 581 s->Indent(); 582 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID()); 583 } 584 585 if (level == lldb::eDescriptionLevelBrief) 586 return; 587 588 if (level != eDescriptionLevelInitial) 589 s->PutCString(": "); 590 591 if (level == lldb::eDescriptionLevelVerbose) 592 s->IndentMore(); 593 594 if (m_address.IsSectionOffset()) 595 { 596 m_address.CalculateSymbolContext(&sc); 597 598 if (level == lldb::eDescriptionLevelFull || level == eDescriptionLevelInitial) 599 { 600 if (IsReExported()) 601 s->PutCString ("re-exported target = "); 602 else 603 s->PutCString("where = "); 604 sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false, true, true); 605 } 606 else 607 { 608 if (sc.module_sp) 609 { 610 s->EOL(); 611 s->Indent("module = "); 612 sc.module_sp->GetFileSpec().Dump (s); 613 } 614 615 if (sc.comp_unit != nullptr) 616 { 617 s->EOL(); 618 s->Indent("compile unit = "); 619 static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s); 620 621 if (sc.function != nullptr) 622 { 623 s->EOL(); 624 s->Indent("function = "); 625 s->PutCString (sc.function->GetName().AsCString("<unknown>")); 626 } 627 628 if (sc.line_entry.line > 0) 629 { 630 s->EOL(); 631 s->Indent("location = "); 632 sc.line_entry.DumpStopContext (s, true); 633 } 634 635 } 636 else 637 { 638 // If we don't have a comp unit, see if we have a symbol we can print. 639 if (sc.symbol) 640 { 641 s->EOL(); 642 if (IsReExported()) 643 s->Indent ("re-exported target = "); 644 else 645 s->Indent("symbol = "); 646 s->PutCString(sc.symbol->GetName().AsCString("<unknown>")); 647 } 648 } 649 } 650 } 651 652 if (level == lldb::eDescriptionLevelVerbose) 653 { 654 s->EOL(); 655 s->Indent(); 656 } 657 658 if (m_address.IsSectionOffset() && (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)) 659 s->Printf (", "); 660 s->Printf ("address = "); 661 662 ExecutionContextScope *exe_scope = nullptr; 663 Target *target = &m_owner.GetTarget(); 664 if (target) 665 exe_scope = target->GetProcessSP().get(); 666 if (exe_scope == nullptr) 667 exe_scope = target; 668 669 if (level == eDescriptionLevelInitial) 670 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress); 671 else 672 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress); 673 674 if (IsIndirect() && m_bp_site_sp) 675 { 676 Address resolved_address; 677 resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target); 678 Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol(); 679 if (resolved_symbol) 680 { 681 if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial) 682 s->Printf (", "); 683 else if (level == lldb::eDescriptionLevelVerbose) 684 { 685 s->EOL(); 686 s->Indent(); 687 } 688 s->Printf ("indirect target = %s", resolved_symbol->GetName().GetCString()); 689 } 690 } 691 692 if (level == lldb::eDescriptionLevelVerbose) 693 { 694 s->EOL(); 695 s->Indent(); 696 s->Printf("resolved = %s\n", IsResolved() ? "true" : "false"); 697 698 s->Indent(); 699 s->Printf ("hit count = %-4u\n", GetHitCount()); 700 701 if (m_options_ap.get()) 702 { 703 s->Indent(); 704 m_options_ap->GetDescription (s, level); 705 s->EOL(); 706 } 707 s->IndentLess(); 708 } 709 else if (level != eDescriptionLevelInitial) 710 { 711 s->Printf(", %sresolved, hit count = %u ", 712 (IsResolved() ? "" : "un"), 713 GetHitCount()); 714 if (m_options_ap.get()) 715 { 716 m_options_ap->GetDescription (s, level); 717 } 718 } 719 } 720 721 void 722 BreakpointLocation::Dump(Stream *s) const 723 { 724 if (s == nullptr) 725 return; 726 727 s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64 " load addr = 0x%8.8" PRIx64 " state = %s type = %s breakpoint " 728 "hw_index = %i hit_count = %-4u ignore_count = %-4u", 729 GetID(), 730 GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(), 731 (uint64_t) m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()), 732 (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled", 733 IsHardware() ? "hardware" : "software", 734 GetHardwareIndex(), 735 GetHitCount(), 736 GetOptionsNoCreate()->GetIgnoreCount()); 737 } 738 739 void 740 BreakpointLocation::SendBreakpointLocationChangedEvent (lldb::BreakpointEventType eventKind) 741 { 742 if (!m_being_created 743 && !m_owner.IsInternal() 744 && m_owner.GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged)) 745 { 746 Breakpoint::BreakpointEventData *data = new Breakpoint::BreakpointEventData (eventKind, 747 m_owner.shared_from_this()); 748 data->GetBreakpointLocationCollection().Add (shared_from_this()); 749 m_owner.GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged, data); 750 } 751 } 752 753 void 754 BreakpointLocation::SwapLocation (BreakpointLocationSP swap_from) 755 { 756 m_address = swap_from->m_address; 757 m_should_resolve_indirect_functions = swap_from->m_should_resolve_indirect_functions; 758 m_is_reexported = swap_from->m_is_reexported; 759 m_is_indirect = swap_from->m_is_indirect; 760 m_user_expression_sp.reset(); 761 } 762