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