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