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 () 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 lldb::BreakpointLocationSP this_sp(this); 153 if (m_options_ap.get()) 154 return m_options_ap->GetThreadPlanToTestCondition (exe_ctx, this_sp, error); 155 else 156 return m_owner.GetThreadPlanToTestCondition (exe_ctx, this_sp, error); 157 } 158 159 const char * 160 BreakpointLocation::GetConditionText () const 161 { 162 return GetOptionsNoCreate()->GetConditionText(); 163 } 164 165 uint32_t 166 BreakpointLocation::GetIgnoreCount () 167 { 168 return GetOptionsNoCreate()->GetIgnoreCount(); 169 } 170 171 void 172 BreakpointLocation::SetIgnoreCount (uint32_t n) 173 { 174 GetLocationOptions()->SetIgnoreCount(n); 175 } 176 177 const BreakpointOptions * 178 BreakpointLocation::GetOptionsNoCreate () const 179 { 180 if (m_options_ap.get() != NULL) 181 return m_options_ap.get(); 182 else 183 return m_owner.GetOptions (); 184 } 185 186 BreakpointOptions * 187 BreakpointLocation::GetLocationOptions () 188 { 189 // If we make the copy we don't copy the callbacks because that is potentially 190 // expensive and we don't want to do that for the simple case where someone is 191 // just disabling the location. 192 if (m_options_ap.get() == NULL) 193 m_options_ap.reset(BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions ())); 194 195 return m_options_ap.get(); 196 } 197 198 bool 199 BreakpointLocation::ValidForThisThread (Thread *thread) 200 { 201 return thread->MatchesSpec(GetOptionsNoCreate()->GetThreadSpecNoCreate()); 202 } 203 204 // RETURNS - true if we should stop at this breakpoint, false if we 205 // should continue. Note, we don't check the thread spec for the breakpoint 206 // here, since if the breakpoint is not for this thread, then the event won't 207 // even get reported, so the check is redundant. 208 209 bool 210 BreakpointLocation::ShouldStop (StoppointCallbackContext *context) 211 { 212 bool should_stop = true; 213 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 214 215 m_hit_count++; 216 217 if (!IsEnabled()) 218 return false; 219 220 if (m_hit_count <= GetIgnoreCount()) 221 return false; 222 223 // We only run synchronous callbacks in ShouldStop: 224 context->is_synchronous = true; 225 should_stop = InvokeCallback (context); 226 227 if (log) 228 { 229 StreamString s; 230 GetDescription (&s, lldb::eDescriptionLevelVerbose); 231 log->Printf ("Hit breakpoint location: %s, %s.\n", s.GetData(), should_stop ? "stopping" : "continuing"); 232 } 233 234 return should_stop; 235 } 236 237 bool 238 BreakpointLocation::IsResolved () const 239 { 240 return m_bp_site_sp.get() != NULL; 241 } 242 243 lldb::BreakpointSiteSP 244 BreakpointLocation::GetBreakpointSite() const 245 { 246 return m_bp_site_sp; 247 } 248 249 bool 250 BreakpointLocation::ResolveBreakpointSite () 251 { 252 if (m_bp_site_sp) 253 return true; 254 255 Process *process = m_owner.GetTarget().GetProcessSP().get(); 256 if (process == NULL) 257 return false; 258 259 if (m_owner.GetTarget().GetSectionLoadList().IsEmpty()) 260 return false; 261 262 BreakpointLocationSP this_sp(this); 263 264 lldb::break_id_t new_id = process->CreateBreakpointSite (this_sp, false); 265 266 if (new_id == LLDB_INVALID_BREAK_ID) 267 { 268 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 269 if (log) 270 log->Warning ("Tried to add breakpoint site at 0x%llx but it was already present.\n", 271 m_address.GetOpcodeLoadAddress (&m_owner.GetTarget())); 272 return false; 273 } 274 275 return true; 276 } 277 278 bool 279 BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp) 280 { 281 m_bp_site_sp = bp_site_sp; 282 return true; 283 } 284 285 bool 286 BreakpointLocation::ClearBreakpointSite () 287 { 288 if (m_bp_site_sp.get()) 289 { 290 m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(), 291 GetID(), m_bp_site_sp); 292 m_bp_site_sp.reset(); 293 return true; 294 } 295 return false; 296 } 297 298 void 299 BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level) 300 { 301 SymbolContext sc; 302 s->Indent(); 303 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID()); 304 305 if (level == lldb::eDescriptionLevelBrief) 306 return; 307 308 s->PutCString(": "); 309 310 if (level == lldb::eDescriptionLevelVerbose) 311 s->IndentMore(); 312 313 if (m_address.IsSectionOffset()) 314 { 315 m_address.CalculateSymbolContext(&sc); 316 317 if (level == lldb::eDescriptionLevelFull) 318 { 319 s->PutCString("where = "); 320 sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false); 321 } 322 else 323 { 324 if (sc.module_sp) 325 { 326 s->EOL(); 327 s->Indent("module = "); 328 sc.module_sp->GetFileSpec().Dump (s); 329 } 330 331 if (sc.comp_unit != NULL) 332 { 333 s->EOL(); 334 s->Indent("compile unit = "); 335 static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s); 336 337 if (sc.function != NULL) 338 { 339 s->EOL(); 340 s->Indent("function = "); 341 s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>")); 342 } 343 344 if (sc.line_entry.line > 0) 345 { 346 s->EOL(); 347 s->Indent("location = "); 348 sc.line_entry.DumpStopContext (s, true); 349 } 350 351 } 352 else 353 { 354 // If we don't have a comp unit, see if we have a symbol we can print. 355 if (sc.symbol) 356 { 357 s->EOL(); 358 s->Indent("symbol = "); 359 s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>")); 360 } 361 } 362 } 363 } 364 365 if (level == lldb::eDescriptionLevelVerbose) 366 { 367 s->EOL(); 368 s->Indent(); 369 } 370 s->Printf ("%saddress = ", (level == lldb::eDescriptionLevelFull && m_address.IsSectionOffset()) ? ", " : ""); 371 ExecutionContextScope *exe_scope = NULL; 372 Target *target = &m_owner.GetTarget(); 373 if (target) 374 exe_scope = target->GetProcessSP().get(); 375 if (exe_scope == NULL) 376 exe_scope = target; 377 378 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress); 379 380 if (level == lldb::eDescriptionLevelVerbose) 381 { 382 s->EOL(); 383 s->Indent(); 384 s->Printf("resolved = %s\n", IsResolved() ? "true" : "false"); 385 386 s->Indent(); 387 s->Printf ("hit count = %-4u\n", GetHitCount()); 388 389 if (m_options_ap.get()) 390 { 391 s->Indent(); 392 m_options_ap->GetDescription (s, level); 393 s->EOL(); 394 } 395 s->IndentLess(); 396 } 397 else 398 { 399 s->Printf(", %sresolved, hit count = %u ", 400 (IsResolved() ? "" : "un"), 401 GetHitCount()); 402 if (m_options_ap.get()) 403 { 404 m_options_ap->GetDescription (s, level); 405 } 406 } 407 } 408 409 void 410 BreakpointLocation::Dump(Stream *s) const 411 { 412 if (s == NULL) 413 return; 414 415 s->Printf("BreakpointLocation %u: tid = %4.4x load addr = 0x%8.8llx state = %s type = %s breakpoint " 416 "hw_index = %i hit_count = %-4u ignore_count = %-4u", 417 GetID(), 418 GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(), 419 (uint64_t) m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()), 420 (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled", 421 IsHardware() ? "hardware" : "software", 422 GetHardwareIndex(), 423 GetHitCount(), 424 m_options_ap.get() ? m_options_ap->GetIgnoreCount() : m_owner.GetIgnoreCount()); 425 } 426