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 const char * 239 BreakpointLocation::GetConditionText () const 240 { 241 return GetOptionsNoCreate()->GetConditionText(); 242 } 243 244 uint32_t 245 BreakpointLocation::GetIgnoreCount () 246 { 247 return GetOptionsNoCreate()->GetIgnoreCount(); 248 } 249 250 void 251 BreakpointLocation::SetIgnoreCount (uint32_t n) 252 { 253 GetLocationOptions()->SetIgnoreCount(n); 254 SendBreakpointLocationChangedEvent (eBreakpointEventTypeIgnoreChanged); 255 } 256 257 const BreakpointOptions * 258 BreakpointLocation::GetOptionsNoCreate () const 259 { 260 if (m_options_ap.get() != NULL) 261 return m_options_ap.get(); 262 else 263 return m_owner.GetOptions (); 264 } 265 266 BreakpointOptions * 267 BreakpointLocation::GetLocationOptions () 268 { 269 // If we make the copy we don't copy the callbacks because that is potentially 270 // expensive and we don't want to do that for the simple case where someone is 271 // just disabling the location. 272 if (m_options_ap.get() == NULL) 273 m_options_ap.reset(BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions ())); 274 275 return m_options_ap.get(); 276 } 277 278 bool 279 BreakpointLocation::ValidForThisThread (Thread *thread) 280 { 281 return thread->MatchesSpec(GetOptionsNoCreate()->GetThreadSpecNoCreate()); 282 } 283 284 // RETURNS - true if we should stop at this breakpoint, false if we 285 // should continue. Note, we don't check the thread spec for the breakpoint 286 // here, since if the breakpoint is not for this thread, then the event won't 287 // even get reported, so the check is redundant. 288 289 bool 290 BreakpointLocation::ShouldStop (StoppointCallbackContext *context) 291 { 292 bool should_stop = true; 293 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 294 295 IncrementHitCount(); 296 297 if (!IsEnabled()) 298 return false; 299 300 if (GetHitCount() <= GetIgnoreCount()) 301 return false; 302 303 // We only run synchronous callbacks in ShouldStop: 304 context->is_synchronous = true; 305 should_stop = InvokeCallback (context); 306 307 if (log) 308 { 309 StreamString s; 310 GetDescription (&s, lldb::eDescriptionLevelVerbose); 311 log->Printf ("Hit breakpoint location: %s, %s.\n", s.GetData(), should_stop ? "stopping" : "continuing"); 312 } 313 314 return should_stop; 315 } 316 317 bool 318 BreakpointLocation::IsResolved () const 319 { 320 return m_bp_site_sp.get() != NULL; 321 } 322 323 lldb::BreakpointSiteSP 324 BreakpointLocation::GetBreakpointSite() const 325 { 326 return m_bp_site_sp; 327 } 328 329 bool 330 BreakpointLocation::ResolveBreakpointSite () 331 { 332 if (m_bp_site_sp) 333 return true; 334 335 Process *process = m_owner.GetTarget().GetProcessSP().get(); 336 if (process == NULL) 337 return false; 338 339 if (m_owner.GetTarget().GetSectionLoadList().IsEmpty()) 340 return false; 341 342 lldb::break_id_t new_id = process->CreateBreakpointSite (shared_from_this(), false); 343 344 if (new_id == LLDB_INVALID_BREAK_ID) 345 { 346 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 347 if (log) 348 log->Warning ("Tried to add breakpoint site at 0x%llx but it was already present.\n", 349 m_address.GetOpcodeLoadAddress (&m_owner.GetTarget())); 350 return false; 351 } 352 353 return true; 354 } 355 356 bool 357 BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp) 358 { 359 m_bp_site_sp = bp_site_sp; 360 return true; 361 } 362 363 bool 364 BreakpointLocation::ClearBreakpointSite () 365 { 366 if (m_bp_site_sp.get()) 367 { 368 m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(), 369 GetID(), m_bp_site_sp); 370 m_bp_site_sp.reset(); 371 return true; 372 } 373 return false; 374 } 375 376 void 377 BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level) 378 { 379 SymbolContext sc; 380 s->Indent(); 381 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID()); 382 383 if (level == lldb::eDescriptionLevelBrief) 384 return; 385 386 s->PutCString(": "); 387 388 if (level == lldb::eDescriptionLevelVerbose) 389 s->IndentMore(); 390 391 if (m_address.IsSectionOffset()) 392 { 393 m_address.CalculateSymbolContext(&sc); 394 395 if (level == lldb::eDescriptionLevelFull) 396 { 397 s->PutCString("where = "); 398 sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false); 399 } 400 else 401 { 402 if (sc.module_sp) 403 { 404 s->EOL(); 405 s->Indent("module = "); 406 sc.module_sp->GetFileSpec().Dump (s); 407 } 408 409 if (sc.comp_unit != NULL) 410 { 411 s->EOL(); 412 s->Indent("compile unit = "); 413 static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s); 414 415 if (sc.function != NULL) 416 { 417 s->EOL(); 418 s->Indent("function = "); 419 s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>")); 420 } 421 422 if (sc.line_entry.line > 0) 423 { 424 s->EOL(); 425 s->Indent("location = "); 426 sc.line_entry.DumpStopContext (s, true); 427 } 428 429 } 430 else 431 { 432 // If we don't have a comp unit, see if we have a symbol we can print. 433 if (sc.symbol) 434 { 435 s->EOL(); 436 s->Indent("symbol = "); 437 s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>")); 438 } 439 } 440 } 441 } 442 443 if (level == lldb::eDescriptionLevelVerbose) 444 { 445 s->EOL(); 446 s->Indent(); 447 } 448 s->Printf ("%saddress = ", (level == lldb::eDescriptionLevelFull && m_address.IsSectionOffset()) ? ", " : ""); 449 ExecutionContextScope *exe_scope = NULL; 450 Target *target = &m_owner.GetTarget(); 451 if (target) 452 exe_scope = target->GetProcessSP().get(); 453 if (exe_scope == NULL) 454 exe_scope = target; 455 456 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress); 457 458 if (level == lldb::eDescriptionLevelVerbose) 459 { 460 s->EOL(); 461 s->Indent(); 462 s->Printf("resolved = %s\n", IsResolved() ? "true" : "false"); 463 464 s->Indent(); 465 s->Printf ("hit count = %-4u\n", GetHitCount()); 466 467 if (m_options_ap.get()) 468 { 469 s->Indent(); 470 m_options_ap->GetDescription (s, level); 471 s->EOL(); 472 } 473 s->IndentLess(); 474 } 475 else 476 { 477 s->Printf(", %sresolved, hit count = %u ", 478 (IsResolved() ? "" : "un"), 479 GetHitCount()); 480 if (m_options_ap.get()) 481 { 482 m_options_ap->GetDescription (s, level); 483 } 484 } 485 } 486 487 void 488 BreakpointLocation::Dump(Stream *s) const 489 { 490 if (s == NULL) 491 return; 492 493 s->Printf("BreakpointLocation %u: tid = %4.4llx load addr = 0x%8.8llx state = %s type = %s breakpoint " 494 "hw_index = %i hit_count = %-4u ignore_count = %-4u", 495 GetID(), 496 GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(), 497 (uint64_t) m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()), 498 (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled", 499 IsHardware() ? "hardware" : "software", 500 GetHardwareIndex(), 501 GetHitCount(), 502 GetOptionsNoCreate()->GetIgnoreCount()); 503 } 504 505 void 506 BreakpointLocation::SendBreakpointLocationChangedEvent (lldb::BreakpointEventType eventKind) 507 { 508 if (!m_being_created 509 && !m_owner.IsInternal() 510 && m_owner.GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged)) 511 { 512 Breakpoint::BreakpointEventData *data = new Breakpoint::BreakpointEventData (eventKind, 513 m_owner.shared_from_this()); 514 data->GetBreakpointLocationCollection().Add (shared_from_this()); 515 m_owner.GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged, data); 516 } 517 } 518 519