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_address (addr), 42 m_owner (owner), 43 m_options_ap (), 44 m_bp_site_sp () 45 { 46 SetThreadID (tid); 47 } 48 49 BreakpointLocation::~BreakpointLocation() 50 { 51 ClearBreakpointSite(); 52 } 53 54 lldb::addr_t 55 BreakpointLocation::GetLoadAddress () const 56 { 57 return m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()); 58 } 59 60 Address & 61 BreakpointLocation::GetAddress () 62 { 63 return m_address; 64 } 65 66 Breakpoint & 67 BreakpointLocation::GetBreakpoint () 68 { 69 return m_owner; 70 } 71 72 bool 73 BreakpointLocation::IsEnabled () const 74 { 75 if (!m_owner.IsEnabled()) 76 return false; 77 else if (m_options_ap.get() != NULL) 78 return m_options_ap->IsEnabled(); 79 else 80 return true; 81 } 82 83 void 84 BreakpointLocation::SetEnabled (bool enabled) 85 { 86 GetLocationOptions()->SetEnabled(enabled); 87 if (enabled) 88 { 89 ResolveBreakpointSite(); 90 } 91 else 92 { 93 ClearBreakpointSite(); 94 } 95 } 96 97 void 98 BreakpointLocation::SetThreadID (lldb::tid_t thread_id) 99 { 100 if (thread_id != LLDB_INVALID_THREAD_ID) 101 GetLocationOptions()->SetThreadID(thread_id); 102 else 103 { 104 // If we're resetting this to an invalid thread id, then 105 // don't make an options pointer just to do that. 106 if (m_options_ap.get() != NULL) 107 m_options_ap->SetThreadID (thread_id); 108 } 109 } 110 111 bool 112 BreakpointLocation::InvokeCallback (StoppointCallbackContext *context) 113 { 114 if (m_options_ap.get() != NULL && m_options_ap->HasCallback()) 115 return m_options_ap->InvokeCallback (context, m_owner.GetID(), GetID()); 116 else 117 return m_owner.InvokeCallback (context, GetID()); 118 } 119 120 void 121 BreakpointLocation::SetCallback (BreakpointHitCallback callback, void *baton, 122 bool is_synchronous) 123 { 124 // The default "Baton" class will keep a copy of "baton" and won't free 125 // or delete it when it goes goes out of scope. 126 GetLocationOptions()->SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous); 127 } 128 129 void 130 BreakpointLocation::SetCallback (BreakpointHitCallback callback, const BatonSP &baton_sp, 131 bool is_synchronous) 132 { 133 GetLocationOptions()->SetCallback (callback, baton_sp, is_synchronous); 134 } 135 136 137 void 138 BreakpointLocation::ClearCallback () 139 { 140 GetLocationOptions()->ClearCallback(); 141 } 142 143 void 144 BreakpointLocation::SetCondition (const char *condition) 145 { 146 GetLocationOptions()->SetCondition (condition); 147 } 148 149 ThreadPlan * 150 BreakpointLocation::GetThreadPlanToTestCondition (ExecutionContext &exe_ctx, Stream &error) 151 { 152 if (m_options_ap.get()) 153 return m_options_ap->GetThreadPlanToTestCondition (exe_ctx, shared_from_this(), error); 154 else 155 return m_owner.GetThreadPlanToTestCondition (exe_ctx, shared_from_this(), error); 156 } 157 158 const char * 159 BreakpointLocation::GetConditionText () const 160 { 161 return GetOptionsNoCreate()->GetConditionText(); 162 } 163 164 uint32_t 165 BreakpointLocation::GetIgnoreCount () 166 { 167 return GetOptionsNoCreate()->GetIgnoreCount(); 168 } 169 170 void 171 BreakpointLocation::SetIgnoreCount (uint32_t n) 172 { 173 GetLocationOptions()->SetIgnoreCount(n); 174 } 175 176 const BreakpointOptions * 177 BreakpointLocation::GetOptionsNoCreate () const 178 { 179 if (m_options_ap.get() != NULL) 180 return m_options_ap.get(); 181 else 182 return m_owner.GetOptions (); 183 } 184 185 BreakpointOptions * 186 BreakpointLocation::GetLocationOptions () 187 { 188 // If we make the copy we don't copy the callbacks because that is potentially 189 // expensive and we don't want to do that for the simple case where someone is 190 // just disabling the location. 191 if (m_options_ap.get() == NULL) 192 m_options_ap.reset(BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions ())); 193 194 return m_options_ap.get(); 195 } 196 197 bool 198 BreakpointLocation::ValidForThisThread (Thread *thread) 199 { 200 return thread->MatchesSpec(GetOptionsNoCreate()->GetThreadSpecNoCreate()); 201 } 202 203 // RETURNS - true if we should stop at this breakpoint, false if we 204 // should continue. Note, we don't check the thread spec for the breakpoint 205 // here, since if the breakpoint is not for this thread, then the event won't 206 // even get reported, so the check is redundant. 207 208 bool 209 BreakpointLocation::ShouldStop (StoppointCallbackContext *context) 210 { 211 bool should_stop = true; 212 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 213 214 IncrementHitCount(); 215 216 if (!IsEnabled()) 217 return false; 218 219 if (GetHitCount() <= GetIgnoreCount()) 220 return false; 221 222 // We only run synchronous callbacks in ShouldStop: 223 context->is_synchronous = true; 224 should_stop = InvokeCallback (context); 225 226 if (log) 227 { 228 StreamString s; 229 GetDescription (&s, lldb::eDescriptionLevelVerbose); 230 log->Printf ("Hit breakpoint location: %s, %s.\n", s.GetData(), should_stop ? "stopping" : "continuing"); 231 } 232 233 return should_stop; 234 } 235 236 bool 237 BreakpointLocation::IsResolved () const 238 { 239 return m_bp_site_sp.get() != NULL; 240 } 241 242 lldb::BreakpointSiteSP 243 BreakpointLocation::GetBreakpointSite() const 244 { 245 return m_bp_site_sp; 246 } 247 248 bool 249 BreakpointLocation::ResolveBreakpointSite () 250 { 251 if (m_bp_site_sp) 252 return true; 253 254 Process *process = m_owner.GetTarget().GetProcessSP().get(); 255 if (process == NULL) 256 return false; 257 258 if (m_owner.GetTarget().GetSectionLoadList().IsEmpty()) 259 return false; 260 261 lldb::break_id_t new_id = process->CreateBreakpointSite (shared_from_this(), false); 262 263 if (new_id == LLDB_INVALID_BREAK_ID) 264 { 265 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 266 if (log) 267 log->Warning ("Tried to add breakpoint site at 0x%llx but it was already present.\n", 268 m_address.GetOpcodeLoadAddress (&m_owner.GetTarget())); 269 return false; 270 } 271 272 return true; 273 } 274 275 bool 276 BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp) 277 { 278 m_bp_site_sp = bp_site_sp; 279 return true; 280 } 281 282 bool 283 BreakpointLocation::ClearBreakpointSite () 284 { 285 if (m_bp_site_sp.get()) 286 { 287 m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(), 288 GetID(), m_bp_site_sp); 289 m_bp_site_sp.reset(); 290 return true; 291 } 292 return false; 293 } 294 295 void 296 BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level) 297 { 298 SymbolContext sc; 299 s->Indent(); 300 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID()); 301 302 if (level == lldb::eDescriptionLevelBrief) 303 return; 304 305 s->PutCString(": "); 306 307 if (level == lldb::eDescriptionLevelVerbose) 308 s->IndentMore(); 309 310 if (m_address.IsSectionOffset()) 311 { 312 m_address.CalculateSymbolContext(&sc); 313 314 if (level == lldb::eDescriptionLevelFull) 315 { 316 s->PutCString("where = "); 317 sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false); 318 } 319 else 320 { 321 if (sc.module_sp) 322 { 323 s->EOL(); 324 s->Indent("module = "); 325 sc.module_sp->GetFileSpec().Dump (s); 326 } 327 328 if (sc.comp_unit != NULL) 329 { 330 s->EOL(); 331 s->Indent("compile unit = "); 332 static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s); 333 334 if (sc.function != NULL) 335 { 336 s->EOL(); 337 s->Indent("function = "); 338 s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>")); 339 } 340 341 if (sc.line_entry.line > 0) 342 { 343 s->EOL(); 344 s->Indent("location = "); 345 sc.line_entry.DumpStopContext (s, true); 346 } 347 348 } 349 else 350 { 351 // If we don't have a comp unit, see if we have a symbol we can print. 352 if (sc.symbol) 353 { 354 s->EOL(); 355 s->Indent("symbol = "); 356 s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>")); 357 } 358 } 359 } 360 } 361 362 if (level == lldb::eDescriptionLevelVerbose) 363 { 364 s->EOL(); 365 s->Indent(); 366 } 367 s->Printf ("%saddress = ", (level == lldb::eDescriptionLevelFull && m_address.IsSectionOffset()) ? ", " : ""); 368 ExecutionContextScope *exe_scope = NULL; 369 Target *target = &m_owner.GetTarget(); 370 if (target) 371 exe_scope = target->GetProcessSP().get(); 372 if (exe_scope == NULL) 373 exe_scope = target; 374 375 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress); 376 377 if (level == lldb::eDescriptionLevelVerbose) 378 { 379 s->EOL(); 380 s->Indent(); 381 s->Printf("resolved = %s\n", IsResolved() ? "true" : "false"); 382 383 s->Indent(); 384 s->Printf ("hit count = %-4u\n", GetHitCount()); 385 386 if (m_options_ap.get()) 387 { 388 s->Indent(); 389 m_options_ap->GetDescription (s, level); 390 s->EOL(); 391 } 392 s->IndentLess(); 393 } 394 else 395 { 396 s->Printf(", %sresolved, hit count = %u ", 397 (IsResolved() ? "" : "un"), 398 GetHitCount()); 399 if (m_options_ap.get()) 400 { 401 m_options_ap->GetDescription (s, level); 402 } 403 } 404 } 405 406 void 407 BreakpointLocation::Dump(Stream *s) const 408 { 409 if (s == NULL) 410 return; 411 412 s->Printf("BreakpointLocation %u: tid = %4.4llx load addr = 0x%8.8llx state = %s type = %s breakpoint " 413 "hw_index = %i hit_count = %-4u ignore_count = %-4u", 414 GetID(), 415 GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(), 416 (uint64_t) m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()), 417 (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled", 418 IsHardware() ? "hardware" : "software", 419 GetHardwareIndex(), 420 GetHitCount(), 421 GetOptionsNoCreate()->GetIgnoreCount()); 422 } 423