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 #include "lldb/lldb-python.h" 11 12 // C Includes 13 // C++ Includes 14 #include <string> 15 16 // Other libraries and framework includes 17 // Project includes 18 #include "lldb/lldb-private-log.h" 19 #include "lldb/Breakpoint/BreakpointLocation.h" 20 #include "lldb/Breakpoint/BreakpointID.h" 21 #include "lldb/Breakpoint/StoppointCallbackContext.h" 22 #include "lldb/Core/Debugger.h" 23 #include "lldb/Core/Log.h" 24 #include "lldb/Core/Module.h" 25 #include "lldb/Core/StreamString.h" 26 #include "lldb/Symbol/CompileUnit.h" 27 #include "lldb/Symbol/Symbol.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 ) : 44 StoppointLocation (loc_id, addr.GetOpcodeLoadAddress(&owner.GetTarget()), hardware), 45 m_being_created(true), 46 m_address (addr), 47 m_owner (owner), 48 m_options_ap (), 49 m_bp_site_sp () 50 { 51 SetThreadID (tid); 52 m_being_created = false; 53 } 54 55 BreakpointLocation::~BreakpointLocation() 56 { 57 ClearBreakpointSite(); 58 } 59 60 lldb::addr_t 61 BreakpointLocation::GetLoadAddress () const 62 { 63 return m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()); 64 } 65 66 Address & 67 BreakpointLocation::GetAddress () 68 { 69 return m_address; 70 } 71 72 Breakpoint & 73 BreakpointLocation::GetBreakpoint () 74 { 75 return m_owner; 76 } 77 78 bool 79 BreakpointLocation::IsEnabled () const 80 { 81 if (!m_owner.IsEnabled()) 82 return false; 83 else if (m_options_ap.get() != NULL) 84 return m_options_ap->IsEnabled(); 85 else 86 return true; 87 } 88 89 void 90 BreakpointLocation::SetEnabled (bool enabled) 91 { 92 GetLocationOptions()->SetEnabled(enabled); 93 if (enabled) 94 { 95 ResolveBreakpointSite(); 96 } 97 else 98 { 99 ClearBreakpointSite(); 100 } 101 SendBreakpointLocationChangedEvent (enabled ? eBreakpointEventTypeEnabled : eBreakpointEventTypeDisabled); 102 } 103 104 void 105 BreakpointLocation::SetThreadID (lldb::tid_t thread_id) 106 { 107 if (thread_id != LLDB_INVALID_THREAD_ID) 108 GetLocationOptions()->SetThreadID(thread_id); 109 else 110 { 111 // If we're resetting this to an invalid thread id, then 112 // don't make an options pointer just to do that. 113 if (m_options_ap.get() != NULL) 114 m_options_ap->SetThreadID (thread_id); 115 } 116 SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged); 117 } 118 119 lldb::tid_t 120 BreakpointLocation::GetThreadID () 121 { 122 if (GetOptionsNoCreate()->GetThreadSpecNoCreate()) 123 return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(); 124 else 125 return LLDB_INVALID_THREAD_ID; 126 } 127 128 void 129 BreakpointLocation::SetThreadIndex (uint32_t index) 130 { 131 if (index != 0) 132 GetLocationOptions()->GetThreadSpec()->SetIndex(index); 133 else 134 { 135 // If we're resetting this to an invalid thread id, then 136 // don't make an options pointer just to do that. 137 if (m_options_ap.get() != NULL) 138 m_options_ap->GetThreadSpec()->SetIndex(index); 139 } 140 SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged); 141 142 } 143 144 uint32_t 145 BreakpointLocation::GetThreadIndex() const 146 { 147 if (GetOptionsNoCreate()->GetThreadSpecNoCreate()) 148 return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetIndex(); 149 else 150 return 0; 151 } 152 153 void 154 BreakpointLocation::SetThreadName (const char *thread_name) 155 { 156 if (thread_name != NULL) 157 GetLocationOptions()->GetThreadSpec()->SetName(thread_name); 158 else 159 { 160 // If we're resetting this to an invalid thread id, then 161 // don't make an options pointer just to do that. 162 if (m_options_ap.get() != NULL) 163 m_options_ap->GetThreadSpec()->SetName(thread_name); 164 } 165 SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged); 166 } 167 168 const char * 169 BreakpointLocation::GetThreadName () const 170 { 171 if (GetOptionsNoCreate()->GetThreadSpecNoCreate()) 172 return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetName(); 173 else 174 return NULL; 175 } 176 177 void 178 BreakpointLocation::SetQueueName (const char *queue_name) 179 { 180 if (queue_name != NULL) 181 GetLocationOptions()->GetThreadSpec()->SetQueueName(queue_name); 182 else 183 { 184 // If we're resetting this to an invalid thread id, then 185 // don't make an options pointer just to do that. 186 if (m_options_ap.get() != NULL) 187 m_options_ap->GetThreadSpec()->SetQueueName(queue_name); 188 } 189 SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged); 190 } 191 192 const char * 193 BreakpointLocation::GetQueueName () const 194 { 195 if (GetOptionsNoCreate()->GetThreadSpecNoCreate()) 196 return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetQueueName(); 197 else 198 return NULL; 199 } 200 201 bool 202 BreakpointLocation::InvokeCallback (StoppointCallbackContext *context) 203 { 204 if (m_options_ap.get() != NULL && m_options_ap->HasCallback()) 205 return m_options_ap->InvokeCallback (context, m_owner.GetID(), GetID()); 206 else 207 return m_owner.InvokeCallback (context, GetID()); 208 } 209 210 void 211 BreakpointLocation::SetCallback (BreakpointHitCallback callback, void *baton, 212 bool is_synchronous) 213 { 214 // The default "Baton" class will keep a copy of "baton" and won't free 215 // or delete it when it goes goes out of scope. 216 GetLocationOptions()->SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous); 217 SendBreakpointLocationChangedEvent (eBreakpointEventTypeCommandChanged); 218 } 219 220 void 221 BreakpointLocation::SetCallback (BreakpointHitCallback callback, const BatonSP &baton_sp, 222 bool is_synchronous) 223 { 224 GetLocationOptions()->SetCallback (callback, baton_sp, is_synchronous); 225 SendBreakpointLocationChangedEvent (eBreakpointEventTypeCommandChanged); 226 } 227 228 229 void 230 BreakpointLocation::ClearCallback () 231 { 232 GetLocationOptions()->ClearCallback(); 233 } 234 235 void 236 BreakpointLocation::SetCondition (const char *condition) 237 { 238 GetLocationOptions()->SetCondition (condition); 239 SendBreakpointLocationChangedEvent (eBreakpointEventTypeConditionChanged); 240 } 241 242 const char * 243 BreakpointLocation::GetConditionText () const 244 { 245 return GetOptionsNoCreate()->GetConditionText(); 246 } 247 248 uint32_t 249 BreakpointLocation::GetIgnoreCount () 250 { 251 return GetOptionsNoCreate()->GetIgnoreCount(); 252 } 253 254 void 255 BreakpointLocation::SetIgnoreCount (uint32_t n) 256 { 257 GetLocationOptions()->SetIgnoreCount(n); 258 SendBreakpointLocationChangedEvent (eBreakpointEventTypeIgnoreChanged); 259 } 260 261 void 262 BreakpointLocation::DecrementIgnoreCount() 263 { 264 if (m_options_ap.get() != NULL) 265 { 266 uint32_t loc_ignore = m_options_ap->GetIgnoreCount(); 267 if (loc_ignore != 0) 268 m_options_ap->SetIgnoreCount(loc_ignore - 1); 269 } 270 } 271 272 bool 273 BreakpointLocation::IgnoreCountShouldStop() 274 { 275 if (m_options_ap.get() != NULL) 276 { 277 uint32_t loc_ignore = m_options_ap->GetIgnoreCount(); 278 if (loc_ignore != 0) 279 { 280 m_owner.DecrementIgnoreCount(); 281 DecrementIgnoreCount(); // Have to decrement our owners' ignore count, since it won't get a 282 // chance to. 283 return false; 284 } 285 } 286 return true; 287 } 288 289 const BreakpointOptions * 290 BreakpointLocation::GetOptionsNoCreate () const 291 { 292 if (m_options_ap.get() != NULL) 293 return m_options_ap.get(); 294 else 295 return m_owner.GetOptions (); 296 } 297 298 BreakpointOptions * 299 BreakpointLocation::GetLocationOptions () 300 { 301 // If we make the copy we don't copy the callbacks because that is potentially 302 // expensive and we don't want to do that for the simple case where someone is 303 // just disabling the location. 304 if (m_options_ap.get() == NULL) 305 m_options_ap.reset(BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions ())); 306 307 return m_options_ap.get(); 308 } 309 310 bool 311 BreakpointLocation::ValidForThisThread (Thread *thread) 312 { 313 return thread->MatchesSpec(GetOptionsNoCreate()->GetThreadSpecNoCreate()); 314 } 315 316 // RETURNS - true if we should stop at this breakpoint, false if we 317 // should continue. Note, we don't check the thread spec for the breakpoint 318 // here, since if the breakpoint is not for this thread, then the event won't 319 // even get reported, so the check is redundant. 320 321 bool 322 BreakpointLocation::ShouldStop (StoppointCallbackContext *context) 323 { 324 bool should_stop = true; 325 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 326 327 IncrementHitCount(); 328 329 if (!IsEnabled()) 330 return false; 331 332 if (!IgnoreCountShouldStop()) 333 return false; 334 335 if (!m_owner.IgnoreCountShouldStop()) 336 return false; 337 338 // We only run synchronous callbacks in ShouldStop: 339 context->is_synchronous = true; 340 should_stop = InvokeCallback (context); 341 342 if (log) 343 { 344 StreamString s; 345 GetDescription (&s, lldb::eDescriptionLevelVerbose); 346 log->Printf ("Hit breakpoint location: %s, %s.\n", s.GetData(), should_stop ? "stopping" : "continuing"); 347 } 348 349 return should_stop; 350 } 351 352 bool 353 BreakpointLocation::IsResolved () const 354 { 355 return m_bp_site_sp.get() != NULL; 356 } 357 358 lldb::BreakpointSiteSP 359 BreakpointLocation::GetBreakpointSite() const 360 { 361 return m_bp_site_sp; 362 } 363 364 bool 365 BreakpointLocation::ResolveBreakpointSite () 366 { 367 if (m_bp_site_sp) 368 return true; 369 370 Process *process = m_owner.GetTarget().GetProcessSP().get(); 371 if (process == NULL) 372 return false; 373 374 if (m_owner.GetTarget().GetSectionLoadList().IsEmpty()) 375 return false; 376 377 lldb::break_id_t new_id = process->CreateBreakpointSite (shared_from_this(), false); 378 379 if (new_id == LLDB_INVALID_BREAK_ID) 380 { 381 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 382 if (log) 383 log->Warning ("Tried to add breakpoint site at 0x%" PRIx64 " but it was already present.\n", 384 m_address.GetOpcodeLoadAddress (&m_owner.GetTarget())); 385 return false; 386 } 387 388 return true; 389 } 390 391 bool 392 BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp) 393 { 394 m_bp_site_sp = bp_site_sp; 395 return true; 396 } 397 398 bool 399 BreakpointLocation::ClearBreakpointSite () 400 { 401 if (m_bp_site_sp.get()) 402 { 403 m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(), 404 GetID(), m_bp_site_sp); 405 m_bp_site_sp.reset(); 406 return true; 407 } 408 return false; 409 } 410 411 void 412 BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level) 413 { 414 SymbolContext sc; 415 416 // If the description level is "initial" then the breakpoint is printing out our initial state, 417 // and we should let it decide how it wants to print our label. 418 if (level != eDescriptionLevelInitial) 419 { 420 s->Indent(); 421 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID()); 422 } 423 424 if (level == lldb::eDescriptionLevelBrief) 425 return; 426 427 if (level != eDescriptionLevelInitial) 428 s->PutCString(": "); 429 430 if (level == lldb::eDescriptionLevelVerbose) 431 s->IndentMore(); 432 433 if (m_address.IsSectionOffset()) 434 { 435 m_address.CalculateSymbolContext(&sc); 436 437 if (level == lldb::eDescriptionLevelFull || level == eDescriptionLevelInitial) 438 { 439 s->PutCString("where = "); 440 sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false); 441 } 442 else 443 { 444 if (sc.module_sp) 445 { 446 s->EOL(); 447 s->Indent("module = "); 448 sc.module_sp->GetFileSpec().Dump (s); 449 } 450 451 if (sc.comp_unit != NULL) 452 { 453 s->EOL(); 454 s->Indent("compile unit = "); 455 static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s); 456 457 if (sc.function != NULL) 458 { 459 s->EOL(); 460 s->Indent("function = "); 461 s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>")); 462 } 463 464 if (sc.line_entry.line > 0) 465 { 466 s->EOL(); 467 s->Indent("location = "); 468 sc.line_entry.DumpStopContext (s, true); 469 } 470 471 } 472 else 473 { 474 // If we don't have a comp unit, see if we have a symbol we can print. 475 if (sc.symbol) 476 { 477 s->EOL(); 478 s->Indent("symbol = "); 479 s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>")); 480 } 481 } 482 } 483 } 484 485 if (level == lldb::eDescriptionLevelVerbose) 486 { 487 s->EOL(); 488 s->Indent(); 489 } 490 491 if (m_address.IsSectionOffset() && (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)) 492 s->Printf (", "); 493 s->Printf ("address = "); 494 495 ExecutionContextScope *exe_scope = NULL; 496 Target *target = &m_owner.GetTarget(); 497 if (target) 498 exe_scope = target->GetProcessSP().get(); 499 if (exe_scope == NULL) 500 exe_scope = target; 501 502 if (eDescriptionLevelInitial) 503 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress); 504 else 505 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress); 506 507 if (level == lldb::eDescriptionLevelVerbose) 508 { 509 s->EOL(); 510 s->Indent(); 511 s->Printf("resolved = %s\n", IsResolved() ? "true" : "false"); 512 513 s->Indent(); 514 s->Printf ("hit count = %-4u\n", GetHitCount()); 515 516 if (m_options_ap.get()) 517 { 518 s->Indent(); 519 m_options_ap->GetDescription (s, level); 520 s->EOL(); 521 } 522 s->IndentLess(); 523 } 524 else if (level != eDescriptionLevelInitial) 525 { 526 s->Printf(", %sresolved, hit count = %u ", 527 (IsResolved() ? "" : "un"), 528 GetHitCount()); 529 if (m_options_ap.get()) 530 { 531 m_options_ap->GetDescription (s, level); 532 } 533 } 534 } 535 536 void 537 BreakpointLocation::Dump(Stream *s) const 538 { 539 if (s == NULL) 540 return; 541 542 s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64 " load addr = 0x%8.8" PRIx64 " state = %s type = %s breakpoint " 543 "hw_index = %i hit_count = %-4u ignore_count = %-4u", 544 GetID(), 545 GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(), 546 (uint64_t) m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()), 547 (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled", 548 IsHardware() ? "hardware" : "software", 549 GetHardwareIndex(), 550 GetHitCount(), 551 GetOptionsNoCreate()->GetIgnoreCount()); 552 } 553 554 void 555 BreakpointLocation::SendBreakpointLocationChangedEvent (lldb::BreakpointEventType eventKind) 556 { 557 if (!m_being_created 558 && !m_owner.IsInternal() 559 && m_owner.GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged)) 560 { 561 Breakpoint::BreakpointEventData *data = new Breakpoint::BreakpointEventData (eventKind, 562 m_owner.shared_from_this()); 563 data->GetBreakpointLocationCollection().Add (shared_from_this()); 564 m_owner.GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged, data); 565 } 566 } 567 568