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