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