BreakpointLocation.cpp revision ac35442b2b1a35ea3100c870214977e3bddb76f6
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 29using namespace lldb; 30using namespace lldb_private; 31 32BreakpointLocation::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 49BreakpointLocation::~BreakpointLocation() 50{ 51 ClearBreakpointSite(); 52} 53 54lldb::addr_t 55BreakpointLocation::GetLoadAddress () const 56{ 57 return m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()); 58} 59 60Address & 61BreakpointLocation::GetAddress () 62{ 63 return m_address; 64} 65 66Breakpoint & 67BreakpointLocation::GetBreakpoint () 68{ 69 return m_owner; 70} 71 72bool 73BreakpointLocation::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 83void 84BreakpointLocation::SetEnabled (bool enabled) 85{ 86 GetLocationOptions()->SetEnabled(enabled); 87 if (enabled) 88 { 89 ResolveBreakpointSite(); 90 } 91 else 92 { 93 ClearBreakpointSite(); 94 } 95} 96 97void 98BreakpointLocation::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 111bool 112BreakpointLocation::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 120void 121BreakpointLocation::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 129void 130BreakpointLocation::SetCallback (BreakpointHitCallback callback, const BatonSP &baton_sp, 131 bool is_synchronous) 132{ 133 GetLocationOptions()->SetCallback (callback, baton_sp, is_synchronous); 134} 135 136 137void 138BreakpointLocation::ClearCallback () 139{ 140 GetLocationOptions()->ClearCallback(); 141} 142 143void 144BreakpointLocation::SetCondition (const char *condition) 145{ 146 GetLocationOptions()->SetCondition (condition); 147} 148 149ThreadPlan * 150BreakpointLocation::GetThreadPlanToTestCondition (ExecutionContext &exe_ctx, Stream &error) 151{ 152 lldb::BreakpointLocationSP my_sp(m_owner.GetLocationSP(this)); 153 if (m_options_ap.get()) 154 return m_options_ap->GetThreadPlanToTestCondition (exe_ctx, my_sp, error); 155 else 156 return m_owner.GetThreadPlanToTestCondition (exe_ctx, my_sp, error); 157} 158 159const char * 160BreakpointLocation::GetConditionText () const 161{ 162 return GetOptionsNoCreate()->GetConditionText(); 163} 164 165uint32_t 166BreakpointLocation::GetIgnoreCount () 167{ 168 return GetOptionsNoCreate()->GetIgnoreCount(); 169} 170 171void 172BreakpointLocation::SetIgnoreCount (uint32_t n) 173{ 174 GetLocationOptions()->SetIgnoreCount(n); 175} 176 177const BreakpointOptions * 178BreakpointLocation::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 186BreakpointOptions * 187BreakpointLocation::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 198bool 199BreakpointLocation::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 209bool 210BreakpointLocation::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 // The SYNCHRONOUS callback says we should stop, next try the condition. 228 229 if (should_stop && GetConditionText() != NULL) 230 { 231 // We need to make sure the user sees any parse errors in their condition, so we'll hook the 232 // constructor errors up to the debugger's Async I/O. 233 234 StreamString errors; 235 ThreadPlanSP condition_plan_sp(GetThreadPlanToTestCondition(context->exe_ctx, errors)); 236 237 if (condition_plan_sp == NULL) 238 { 239 if (log) 240 log->Printf("Error evaluating condition: \"%s\"\n", errors.GetData()); 241 242 Debugger &debugger = context->exe_ctx.target->GetDebugger(); 243 StreamSP error_sp = debugger.GetAsyncErrorStream (); 244 error_sp->PutCString ("Error parsing breakpoint condition:\n"); 245 error_sp->PutCString (errors.GetData()); 246 error_sp->EOL(); 247 error_sp->Flush(); 248 249 } 250 else 251 { 252 // Queue our condition, then continue so that we can run it. 253 context->exe_ctx.thread->QueueThreadPlan(condition_plan_sp, false); 254 should_stop = false; 255 } 256 } 257 258 if (log) 259 { 260 StreamString s; 261 GetDescription (&s, lldb::eDescriptionLevelVerbose); 262 log->Printf ("Hit breakpoint location: %s, %s.\n", s.GetData(), should_stop ? "stopping" : "continuing"); 263 } 264 265 return should_stop; 266} 267 268bool 269BreakpointLocation::IsResolved () const 270{ 271 return m_bp_site_sp.get() != NULL; 272} 273 274lldb::BreakpointSiteSP 275BreakpointLocation::GetBreakpointSite() const 276{ 277 return m_bp_site_sp; 278} 279 280bool 281BreakpointLocation::ResolveBreakpointSite () 282{ 283 if (m_bp_site_sp) 284 return true; 285 286 Process *process = m_owner.GetTarget().GetProcessSP().get(); 287 if (process == NULL) 288 return false; 289 290 if (m_owner.GetTarget().GetSectionLoadList().IsEmpty()) 291 return false; 292 293 BreakpointLocationSP myself_sp(m_owner.GetLocationSP (this)); 294 295 lldb::break_id_t new_id = process->CreateBreakpointSite (myself_sp, false); 296 297 if (new_id == LLDB_INVALID_BREAK_ID) 298 { 299 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); 300 if (log) 301 log->Warning ("Tried to add breakpoint site at 0x%llx but it was already present.\n", 302 m_address.GetOpcodeLoadAddress (&m_owner.GetTarget())); 303 return false; 304 } 305 306 return true; 307} 308 309bool 310BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp) 311{ 312 m_bp_site_sp = bp_site_sp; 313 return true; 314} 315 316bool 317BreakpointLocation::ClearBreakpointSite () 318{ 319 if (m_bp_site_sp.get()) 320 { 321 m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(), 322 GetID(), m_bp_site_sp); 323 m_bp_site_sp.reset(); 324 return true; 325 } 326 return false; 327} 328 329void 330BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level) 331{ 332 SymbolContext sc; 333 s->Indent(); 334 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID()); 335 336 if (level == lldb::eDescriptionLevelBrief) 337 return; 338 339 s->PutCString(": "); 340 341 if (level == lldb::eDescriptionLevelVerbose) 342 s->IndentMore(); 343 344 if (m_address.IsSectionOffset()) 345 { 346 m_address.CalculateSymbolContext(&sc); 347 348 if (level == lldb::eDescriptionLevelFull) 349 { 350 s->PutCString("where = "); 351 sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false); 352 } 353 else 354 { 355 if (sc.module_sp) 356 { 357 s->EOL(); 358 s->Indent("module = "); 359 sc.module_sp->GetFileSpec().Dump (s); 360 } 361 362 if (sc.comp_unit != NULL) 363 { 364 s->EOL(); 365 s->Indent("compile unit = "); 366 static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s); 367 368 if (sc.function != NULL) 369 { 370 s->EOL(); 371 s->Indent("function = "); 372 s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>")); 373 } 374 375 if (sc.line_entry.line > 0) 376 { 377 s->EOL(); 378 s->Indent("location = "); 379 sc.line_entry.DumpStopContext (s, true); 380 } 381 382 } 383 else 384 { 385 // If we don't have a comp unit, see if we have a symbol we can print. 386 if (sc.symbol) 387 { 388 s->EOL(); 389 s->Indent("symbol = "); 390 s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>")); 391 } 392 } 393 } 394 } 395 396 if (level == lldb::eDescriptionLevelVerbose) 397 { 398 s->EOL(); 399 s->Indent(); 400 } 401 s->Printf ("%saddress = ", (level == lldb::eDescriptionLevelFull && m_address.IsSectionOffset()) ? ", " : ""); 402 ExecutionContextScope *exe_scope = NULL; 403 Target *target = &m_owner.GetTarget(); 404 if (target) 405 exe_scope = target->GetProcessSP().get(); 406 if (exe_scope == NULL) 407 exe_scope = target; 408 409 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress); 410 411 if (level == lldb::eDescriptionLevelVerbose) 412 { 413 s->EOL(); 414 s->Indent(); 415 s->Printf("resolved = %s\n", IsResolved() ? "true" : "false"); 416 417 s->Indent(); 418 s->Printf ("hit count = %-4u\n", GetHitCount()); 419 420 if (m_options_ap.get()) 421 { 422 s->Indent(); 423 m_options_ap->GetDescription (s, level); 424 s->EOL(); 425 } 426 s->IndentLess(); 427 } 428 else 429 { 430 s->Printf(", %sresolved, hit count = %u ", 431 (IsResolved() ? "" : "un"), 432 GetHitCount()); 433 if (m_options_ap.get()) 434 { 435 m_options_ap->GetDescription (s, level); 436 } 437 } 438} 439 440void 441BreakpointLocation::Dump(Stream *s) const 442{ 443 if (s == NULL) 444 return; 445 446 s->Printf("BreakpointLocation %u: tid = %4.4x load addr = 0x%8.8llx state = %s type = %s breakpoint " 447 "hw_index = %i hit_count = %-4u ignore_count = %-4u", 448 GetID(), 449 GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(), 450 (uint64_t) m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()), 451 (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled", 452 IsHardware() ? "hardware" : "software", 453 GetHardwareIndex(), 454 GetHitCount(), 455 m_options_ap.get() ? m_options_ap->GetIgnoreCount() : m_owner.GetIgnoreCount()); 456} 457