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/Log.h" 20 #include "lldb/Target/Target.h" 21 #include "lldb/Target/ThreadPlan.h" 22 #include "lldb/Target/Process.h" 23 #include "lldb/Core/StreamString.h" 24 #include "lldb/lldb-private-log.h" 25 #include "lldb/Target/Thread.h" 26 #include "lldb/Target/ThreadSpec.h" 27 28 using namespace lldb; 29 using namespace lldb_private; 30 31 BreakpointLocation::BreakpointLocation 32 ( 33 break_id_t loc_id, 34 Breakpoint &owner, 35 const Address &addr, 36 lldb::tid_t tid, 37 bool hardware 38 ) : 39 StoppointLocation (loc_id, addr.GetOpcodeLoadAddress(&owner.GetTarget()), hardware), 40 m_address (addr), 41 m_owner (owner), 42 m_options_ap (), 43 m_bp_site_sp () 44 { 45 SetThreadID (tid); 46 } 47 48 BreakpointLocation::~BreakpointLocation() 49 { 50 ClearBreakpointSite(); 51 } 52 53 lldb::addr_t 54 BreakpointLocation::GetLoadAddress () const 55 { 56 return m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()); 57 } 58 59 Address & 60 BreakpointLocation::GetAddress () 61 { 62 return m_address; 63 } 64 65 Breakpoint & 66 BreakpointLocation::GetBreakpoint () 67 { 68 return m_owner; 69 } 70 71 bool 72 BreakpointLocation::IsEnabled () 73 { 74 if (!m_owner.IsEnabled()) 75 return false; 76 else if (m_options_ap.get() != NULL) 77 return m_options_ap->IsEnabled(); 78 else 79 return true; 80 } 81 82 void 83 BreakpointLocation::SetEnabled (bool enabled) 84 { 85 GetLocationOptions()->SetEnabled(enabled); 86 if (enabled) 87 { 88 ResolveBreakpointSite(); 89 } 90 else 91 { 92 ClearBreakpointSite(); 93 } 94 } 95 96 void 97 BreakpointLocation::SetThreadID (lldb::tid_t thread_id) 98 { 99 if (thread_id != LLDB_INVALID_THREAD_ID) 100 GetLocationOptions()->SetThreadID(thread_id); 101 else 102 { 103 // If we're resetting this to an invalid thread id, then 104 // don't make an options pointer just to do that. 105 if (m_options_ap.get() != NULL) 106 m_options_ap->SetThreadID (thread_id); 107 } 108 } 109 110 bool 111 BreakpointLocation::InvokeCallback (StoppointCallbackContext *context) 112 { 113 if (m_options_ap.get() != NULL && m_options_ap->HasCallback()) 114 return m_options_ap->InvokeCallback (context, m_owner.GetID(), GetID()); 115 else 116 return m_owner.InvokeCallback (context, GetID()); 117 } 118 119 void 120 BreakpointLocation::SetCallback (BreakpointHitCallback callback, void *baton, 121 bool is_synchronous) 122 { 123 // The default "Baton" class will keep a copy of "baton" and won't free 124 // or delete it when it goes goes out of scope. 125 GetLocationOptions()->SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous); 126 } 127 128 void 129 BreakpointLocation::SetCallback (BreakpointHitCallback callback, const BatonSP &baton_sp, 130 bool is_synchronous) 131 { 132 GetLocationOptions()->SetCallback (callback, baton_sp, is_synchronous); 133 } 134 135 136 void 137 BreakpointLocation::ClearCallback () 138 { 139 GetLocationOptions()->ClearCallback(); 140 } 141 142 void 143 BreakpointLocation::SetCondition (const char *condition) 144 { 145 GetLocationOptions()->SetCondition (condition); 146 } 147 148 ThreadPlan * 149 BreakpointLocation::GetThreadPlanToTestCondition (ExecutionContext &exe_ctx, Stream &error) 150 { 151 lldb::BreakpointLocationSP my_sp(m_owner.GetLocationSP(this)); 152 if (m_options_ap.get()) 153 return m_options_ap->GetThreadPlanToTestCondition (exe_ctx, my_sp, error); 154 else 155 return m_owner.GetThreadPlanToTestCondition (exe_ctx, my_sp, error); 156 } 157 158 const char * 159 BreakpointLocation::GetConditionText () 160 { 161 return GetLocationOptions()->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 m_hit_count++; 215 216 if (!IsEnabled()) 217 return false; 218 219 if (m_hit_count <= GetIgnoreCount()) 220 return false; 221 222 // Next in order of importance is the condition. See if it is true: 223 StreamString errors; 224 225 // We only run synchronous callbacks in ShouldStop: 226 context->is_synchronous = true; 227 should_stop = InvokeCallback (context); 228 229 // The SYNCHRONOUS callback says we should stop, next try the condition. 230 231 if (should_stop) 232 { 233 ThreadPlanSP condition_plan_sp(GetThreadPlanToTestCondition(context->exe_ctx, errors)); 234 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 235 if (log && errors.GetSize() > 0) 236 { 237 log->Printf("Error evaluating condition: \"%s\".\n", errors.GetData()); 238 } 239 else if (condition_plan_sp != NULL) 240 { 241 context->exe_ctx.thread->QueueThreadPlan(condition_plan_sp, false); 242 return false; 243 } 244 } 245 246 if (should_stop) 247 { 248 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 249 if (log) 250 { 251 StreamString s; 252 GetDescription (&s, lldb::eDescriptionLevelVerbose); 253 log->Printf ("Hit breakpoint location: %s\n", s.GetData()); 254 } 255 } 256 return should_stop; 257 } 258 259 bool 260 BreakpointLocation::IsResolved () const 261 { 262 return m_bp_site_sp.get() != NULL; 263 } 264 265 lldb::BreakpointSiteSP 266 BreakpointLocation::GetBreakpointSite() const 267 { 268 return m_bp_site_sp; 269 } 270 271 bool 272 BreakpointLocation::ResolveBreakpointSite () 273 { 274 if (m_bp_site_sp) 275 return true; 276 277 Process *process = m_owner.GetTarget().GetProcessSP().get(); 278 if (process == NULL) 279 return false; 280 281 if (m_owner.GetTarget().GetSectionLoadList().IsEmpty()) 282 return false; 283 284 BreakpointLocationSP myself_sp(m_owner.GetLocationSP (this)); 285 286 lldb::break_id_t new_id = process->CreateBreakpointSite (myself_sp, false); 287 288 if (new_id == LLDB_INVALID_BREAK_ID) 289 { 290 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 291 if (log) 292 log->Warning ("Tried to add breakpoint site at 0x%llx but it was already present.\n", 293 m_address.GetOpcodeLoadAddress (&m_owner.GetTarget())); 294 return false; 295 } 296 297 return true; 298 } 299 300 bool 301 BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp) 302 { 303 m_bp_site_sp = bp_site_sp; 304 return true; 305 } 306 307 bool 308 BreakpointLocation::ClearBreakpointSite () 309 { 310 if (m_bp_site_sp.get()) 311 { 312 m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(), 313 GetID(), m_bp_site_sp); 314 m_bp_site_sp.reset(); 315 return true; 316 } 317 return false; 318 } 319 320 void 321 BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level) 322 { 323 SymbolContext sc; 324 s->Indent(); 325 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID()); 326 327 if (level == lldb::eDescriptionLevelBrief) 328 return; 329 330 s->PutCString(": "); 331 332 if (level == lldb::eDescriptionLevelVerbose) 333 s->IndentMore(); 334 335 if (m_address.IsSectionOffset()) 336 { 337 m_address.CalculateSymbolContext(&sc); 338 339 if (level == lldb::eDescriptionLevelFull) 340 { 341 s->PutCString("where = "); 342 sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false); 343 } 344 else 345 { 346 if (sc.module_sp) 347 { 348 s->EOL(); 349 s->Indent("module = "); 350 sc.module_sp->GetFileSpec().Dump (s); 351 } 352 353 if (sc.comp_unit != NULL) 354 { 355 s->EOL(); 356 s->Indent("compile unit = "); 357 static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s); 358 359 if (sc.function != NULL) 360 { 361 s->EOL(); 362 s->Indent("function = "); 363 s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>")); 364 } 365 366 if (sc.line_entry.line > 0) 367 { 368 s->EOL(); 369 s->Indent("location = "); 370 sc.line_entry.DumpStopContext (s, true); 371 } 372 373 } 374 else 375 { 376 // If we don't have a comp unit, see if we have a symbol we can print. 377 if (sc.symbol) 378 { 379 s->EOL(); 380 s->Indent("symbol = "); 381 s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>")); 382 } 383 } 384 } 385 } 386 387 if (level == lldb::eDescriptionLevelVerbose) 388 { 389 s->EOL(); 390 s->Indent(); 391 } 392 s->Printf ("%saddress = ", (level == lldb::eDescriptionLevelFull && m_address.IsSectionOffset()) ? ", " : ""); 393 ExecutionContextScope *exe_scope = NULL; 394 Target *target = &m_owner.GetTarget(); 395 if (target) 396 exe_scope = target->GetProcessSP().get(); 397 if (exe_scope == NULL) 398 exe_scope = target; 399 400 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress); 401 402 if (level == lldb::eDescriptionLevelVerbose) 403 { 404 s->EOL(); 405 s->Indent(); 406 s->Printf("resolved = %s\n", IsResolved() ? "true" : "false"); 407 408 s->Indent(); 409 s->Printf ("hit count = %-4u\n", GetHitCount()); 410 411 if (m_options_ap.get()) 412 { 413 s->Indent(); 414 m_options_ap->GetDescription (s, level); 415 s->EOL(); 416 } 417 s->IndentLess(); 418 } 419 else 420 { 421 s->Printf(", %sresolved, hit count = %u ", 422 (IsResolved() ? "" : "un"), 423 GetHitCount()); 424 if (m_options_ap.get()) 425 { 426 m_options_ap->GetDescription (s, level); 427 } 428 } 429 } 430 431 void 432 BreakpointLocation::Dump(Stream *s) const 433 { 434 if (s == NULL) 435 return; 436 437 s->Printf("BreakpointLocation %u: tid = %4.4x load addr = 0x%8.8llx state = %s type = %s breakpoint " 438 "hw_index = %i hit_count = %-4u ignore_count = %-4u", 439 GetID(), 440 GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(), 441 (uint64_t) m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()), 442 (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled", 443 IsHardware() ? "hardware" : "software", 444 GetHardwareIndex(), 445 GetHitCount(), 446 m_options_ap.get() ? m_options_ap->GetIgnoreCount() : m_owner.GetIgnoreCount()); 447 } 448