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