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 #include "lldb/lldb-python.h"
11
12 // C Includes
13 // C++ Includes
14 #include <string>
15
16 // Other libraries and framework includes
17 // Project includes
18 #include "lldb/lldb-private-log.h"
19 #include "lldb/Breakpoint/BreakpointLocation.h"
20 #include "lldb/Breakpoint/BreakpointID.h"
21 #include "lldb/Breakpoint/StoppointCallbackContext.h"
22 #include "lldb/Core/Debugger.h"
23 #include "lldb/Core/Log.h"
24 #include "lldb/Core/Module.h"
25 #include "lldb/Core/StreamString.h"
26 #include "lldb/Symbol/CompileUnit.h"
27 #include "lldb/Symbol/Symbol.h"
28 #include "lldb/Target/Target.h"
29 #include "lldb/Target/Process.h"
30 #include "lldb/Target/Thread.h"
31 #include "lldb/Target/ThreadSpec.h"
32
33 using namespace lldb;
34 using namespace lldb_private;
35
BreakpointLocation(break_id_t loc_id,Breakpoint & owner,const Address & addr,lldb::tid_t tid,bool hardware)36 BreakpointLocation::BreakpointLocation
37 (
38 break_id_t loc_id,
39 Breakpoint &owner,
40 const Address &addr,
41 lldb::tid_t tid,
42 bool hardware
43 ) :
44 StoppointLocation (loc_id, addr.GetOpcodeLoadAddress(&owner.GetTarget()), hardware),
45 m_being_created(true),
46 m_address (addr),
47 m_owner (owner),
48 m_options_ap (),
49 m_bp_site_sp (),
50 m_condition_mutex ()
51 {
52 SetThreadID (tid);
53 m_being_created = false;
54 }
55
~BreakpointLocation()56 BreakpointLocation::~BreakpointLocation()
57 {
58 ClearBreakpointSite();
59 }
60
61 lldb::addr_t
GetLoadAddress() const62 BreakpointLocation::GetLoadAddress () const
63 {
64 return m_address.GetOpcodeLoadAddress (&m_owner.GetTarget());
65 }
66
67 Address &
GetAddress()68 BreakpointLocation::GetAddress ()
69 {
70 return m_address;
71 }
72
73 Breakpoint &
GetBreakpoint()74 BreakpointLocation::GetBreakpoint ()
75 {
76 return m_owner;
77 }
78
79 bool
IsEnabled() const80 BreakpointLocation::IsEnabled () const
81 {
82 if (!m_owner.IsEnabled())
83 return false;
84 else if (m_options_ap.get() != NULL)
85 return m_options_ap->IsEnabled();
86 else
87 return true;
88 }
89
90 void
SetEnabled(bool enabled)91 BreakpointLocation::SetEnabled (bool enabled)
92 {
93 GetLocationOptions()->SetEnabled(enabled);
94 if (enabled)
95 {
96 ResolveBreakpointSite();
97 }
98 else
99 {
100 ClearBreakpointSite();
101 }
102 SendBreakpointLocationChangedEvent (enabled ? eBreakpointEventTypeEnabled : eBreakpointEventTypeDisabled);
103 }
104
105 void
SetThreadID(lldb::tid_t thread_id)106 BreakpointLocation::SetThreadID (lldb::tid_t thread_id)
107 {
108 if (thread_id != LLDB_INVALID_THREAD_ID)
109 GetLocationOptions()->SetThreadID(thread_id);
110 else
111 {
112 // If we're resetting this to an invalid thread id, then
113 // don't make an options pointer just to do that.
114 if (m_options_ap.get() != NULL)
115 m_options_ap->SetThreadID (thread_id);
116 }
117 SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
118 }
119
120 lldb::tid_t
GetThreadID()121 BreakpointLocation::GetThreadID ()
122 {
123 if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
124 return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID();
125 else
126 return LLDB_INVALID_THREAD_ID;
127 }
128
129 void
SetThreadIndex(uint32_t index)130 BreakpointLocation::SetThreadIndex (uint32_t index)
131 {
132 if (index != 0)
133 GetLocationOptions()->GetThreadSpec()->SetIndex(index);
134 else
135 {
136 // If we're resetting this to an invalid thread id, then
137 // don't make an options pointer just to do that.
138 if (m_options_ap.get() != NULL)
139 m_options_ap->GetThreadSpec()->SetIndex(index);
140 }
141 SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
142
143 }
144
145 uint32_t
GetThreadIndex() const146 BreakpointLocation::GetThreadIndex() const
147 {
148 if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
149 return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetIndex();
150 else
151 return 0;
152 }
153
154 void
SetThreadName(const char * thread_name)155 BreakpointLocation::SetThreadName (const char *thread_name)
156 {
157 if (thread_name != NULL)
158 GetLocationOptions()->GetThreadSpec()->SetName(thread_name);
159 else
160 {
161 // If we're resetting this to an invalid thread id, then
162 // don't make an options pointer just to do that.
163 if (m_options_ap.get() != NULL)
164 m_options_ap->GetThreadSpec()->SetName(thread_name);
165 }
166 SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
167 }
168
169 const char *
GetThreadName() const170 BreakpointLocation::GetThreadName () const
171 {
172 if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
173 return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetName();
174 else
175 return NULL;
176 }
177
178 void
SetQueueName(const char * queue_name)179 BreakpointLocation::SetQueueName (const char *queue_name)
180 {
181 if (queue_name != NULL)
182 GetLocationOptions()->GetThreadSpec()->SetQueueName(queue_name);
183 else
184 {
185 // If we're resetting this to an invalid thread id, then
186 // don't make an options pointer just to do that.
187 if (m_options_ap.get() != NULL)
188 m_options_ap->GetThreadSpec()->SetQueueName(queue_name);
189 }
190 SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
191 }
192
193 const char *
GetQueueName() const194 BreakpointLocation::GetQueueName () const
195 {
196 if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
197 return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetQueueName();
198 else
199 return NULL;
200 }
201
202 bool
InvokeCallback(StoppointCallbackContext * context)203 BreakpointLocation::InvokeCallback (StoppointCallbackContext *context)
204 {
205 if (m_options_ap.get() != NULL && m_options_ap->HasCallback())
206 return m_options_ap->InvokeCallback (context, m_owner.GetID(), GetID());
207 else
208 return m_owner.InvokeCallback (context, GetID());
209 }
210
211 void
SetCallback(BreakpointHitCallback callback,void * baton,bool is_synchronous)212 BreakpointLocation::SetCallback (BreakpointHitCallback callback, void *baton,
213 bool is_synchronous)
214 {
215 // The default "Baton" class will keep a copy of "baton" and won't free
216 // or delete it when it goes goes out of scope.
217 GetLocationOptions()->SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
218 SendBreakpointLocationChangedEvent (eBreakpointEventTypeCommandChanged);
219 }
220
221 void
SetCallback(BreakpointHitCallback callback,const BatonSP & baton_sp,bool is_synchronous)222 BreakpointLocation::SetCallback (BreakpointHitCallback callback, const BatonSP &baton_sp,
223 bool is_synchronous)
224 {
225 GetLocationOptions()->SetCallback (callback, baton_sp, is_synchronous);
226 SendBreakpointLocationChangedEvent (eBreakpointEventTypeCommandChanged);
227 }
228
229
230 void
ClearCallback()231 BreakpointLocation::ClearCallback ()
232 {
233 GetLocationOptions()->ClearCallback();
234 }
235
236 void
SetCondition(const char * condition)237 BreakpointLocation::SetCondition (const char *condition)
238 {
239 GetLocationOptions()->SetCondition (condition);
240 SendBreakpointLocationChangedEvent (eBreakpointEventTypeConditionChanged);
241 }
242
243 const char *
GetConditionText(size_t * hash) const244 BreakpointLocation::GetConditionText (size_t *hash) const
245 {
246 return GetOptionsNoCreate()->GetConditionText(hash);
247 }
248
249 bool
ConditionSaysStop(ExecutionContext & exe_ctx,Error & error)250 BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error)
251 {
252 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
253
254 Mutex::Locker evaluation_locker(m_condition_mutex);
255
256 size_t condition_hash;
257 const char *condition_text = GetConditionText(&condition_hash);
258
259 if (!condition_text)
260 {
261 m_user_expression_sp.reset();
262 return false;
263 }
264
265 if (condition_hash != m_condition_hash ||
266 !m_user_expression_sp ||
267 !m_user_expression_sp->MatchesContext(exe_ctx))
268 {
269 m_user_expression_sp.reset(new ClangUserExpression(condition_text,
270 NULL,
271 lldb::eLanguageTypeUnknown,
272 ClangUserExpression::eResultTypeAny));
273
274 StreamString errors;
275
276 if (!m_user_expression_sp->Parse(errors,
277 exe_ctx,
278 eExecutionPolicyOnlyWhenNeeded,
279 true))
280 {
281 error.SetErrorStringWithFormat("Couldn't parse conditional expression:\n%s",
282 errors.GetData());
283 m_user_expression_sp.reset();
284 return false;
285 }
286
287 m_condition_hash = condition_hash;
288 }
289
290 // We need to make sure the user sees any parse errors in their condition, so we'll hook the
291 // constructor errors up to the debugger's Async I/O.
292
293 ValueObjectSP result_value_sp;
294 const bool unwind_on_error = true;
295 const bool ignore_breakpoints = true;
296 const bool try_all_threads = true;
297
298 Error expr_error;
299
300 StreamString execution_errors;
301
302 ClangExpressionVariableSP result_variable_sp;
303
304 ExecutionResults result_code =
305 m_user_expression_sp->Execute(execution_errors,
306 exe_ctx,
307 unwind_on_error,
308 ignore_breakpoints,
309 m_user_expression_sp,
310 result_variable_sp,
311 try_all_threads,
312 ClangUserExpression::kDefaultTimeout);
313
314 bool ret;
315
316 if (result_code == eExecutionCompleted)
317 {
318 if (!result_variable_sp)
319 {
320 ret = false;
321 error.SetErrorString("Expression did not return a result");
322 return false;
323 }
324
325 result_value_sp = result_variable_sp->GetValueObject();
326
327 if (result_value_sp)
328 {
329 Scalar scalar_value;
330 if (result_value_sp->ResolveValue (scalar_value))
331 {
332 if (scalar_value.ULongLong(1) == 0)
333 ret = false;
334 else
335 ret = true;
336 if (log)
337 log->Printf("Condition successfully evaluated, result is %s.\n",
338 ret ? "true" : "false");
339 }
340 else
341 {
342 ret = false;
343 error.SetErrorString("Failed to get an integer result from the expression");
344 }
345 }
346 else
347 {
348 ret = false;
349 error.SetErrorString("Failed to get any result from the expression");
350 }
351 }
352 else
353 {
354 ret = false;
355 error.SetErrorStringWithFormat("Couldn't execute expression:\n%s", execution_errors.GetData());
356 }
357
358 return ret;
359 }
360
361 uint32_t
GetIgnoreCount()362 BreakpointLocation::GetIgnoreCount ()
363 {
364 return GetOptionsNoCreate()->GetIgnoreCount();
365 }
366
367 void
SetIgnoreCount(uint32_t n)368 BreakpointLocation::SetIgnoreCount (uint32_t n)
369 {
370 GetLocationOptions()->SetIgnoreCount(n);
371 SendBreakpointLocationChangedEvent (eBreakpointEventTypeIgnoreChanged);
372 }
373
374 void
DecrementIgnoreCount()375 BreakpointLocation::DecrementIgnoreCount()
376 {
377 if (m_options_ap.get() != NULL)
378 {
379 uint32_t loc_ignore = m_options_ap->GetIgnoreCount();
380 if (loc_ignore != 0)
381 m_options_ap->SetIgnoreCount(loc_ignore - 1);
382 }
383 }
384
385 bool
IgnoreCountShouldStop()386 BreakpointLocation::IgnoreCountShouldStop()
387 {
388 if (m_options_ap.get() != NULL)
389 {
390 uint32_t loc_ignore = m_options_ap->GetIgnoreCount();
391 if (loc_ignore != 0)
392 {
393 m_owner.DecrementIgnoreCount();
394 DecrementIgnoreCount(); // Have to decrement our owners' ignore count, since it won't get a
395 // chance to.
396 return false;
397 }
398 }
399 return true;
400 }
401
402 const BreakpointOptions *
GetOptionsNoCreate() const403 BreakpointLocation::GetOptionsNoCreate () const
404 {
405 if (m_options_ap.get() != NULL)
406 return m_options_ap.get();
407 else
408 return m_owner.GetOptions ();
409 }
410
411 BreakpointOptions *
GetLocationOptions()412 BreakpointLocation::GetLocationOptions ()
413 {
414 // If we make the copy we don't copy the callbacks because that is potentially
415 // expensive and we don't want to do that for the simple case where someone is
416 // just disabling the location.
417 if (m_options_ap.get() == NULL)
418 m_options_ap.reset(BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions ()));
419
420 return m_options_ap.get();
421 }
422
423 bool
ValidForThisThread(Thread * thread)424 BreakpointLocation::ValidForThisThread (Thread *thread)
425 {
426 return thread->MatchesSpec(GetOptionsNoCreate()->GetThreadSpecNoCreate());
427 }
428
429 // RETURNS - true if we should stop at this breakpoint, false if we
430 // should continue. Note, we don't check the thread spec for the breakpoint
431 // here, since if the breakpoint is not for this thread, then the event won't
432 // even get reported, so the check is redundant.
433
434 bool
ShouldStop(StoppointCallbackContext * context)435 BreakpointLocation::ShouldStop (StoppointCallbackContext *context)
436 {
437 bool should_stop = true;
438 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
439
440 IncrementHitCount();
441
442 if (!IsEnabled())
443 return false;
444
445 if (!IgnoreCountShouldStop())
446 return false;
447
448 if (!m_owner.IgnoreCountShouldStop())
449 return false;
450
451 // We only run synchronous callbacks in ShouldStop:
452 context->is_synchronous = true;
453 should_stop = InvokeCallback (context);
454
455 if (log)
456 {
457 StreamString s;
458 GetDescription (&s, lldb::eDescriptionLevelVerbose);
459 log->Printf ("Hit breakpoint location: %s, %s.\n", s.GetData(), should_stop ? "stopping" : "continuing");
460 }
461
462 return should_stop;
463 }
464
465 bool
IsResolved() const466 BreakpointLocation::IsResolved () const
467 {
468 return m_bp_site_sp.get() != NULL;
469 }
470
471 lldb::BreakpointSiteSP
GetBreakpointSite() const472 BreakpointLocation::GetBreakpointSite() const
473 {
474 return m_bp_site_sp;
475 }
476
477 bool
ResolveBreakpointSite()478 BreakpointLocation::ResolveBreakpointSite ()
479 {
480 if (m_bp_site_sp)
481 return true;
482
483 Process *process = m_owner.GetTarget().GetProcessSP().get();
484 if (process == NULL)
485 return false;
486
487 lldb::break_id_t new_id = process->CreateBreakpointSite (shared_from_this(), false);
488
489 if (new_id == LLDB_INVALID_BREAK_ID)
490 {
491 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
492 if (log)
493 log->Warning ("Tried to add breakpoint site at 0x%" PRIx64 " but it was already present.\n",
494 m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()));
495 return false;
496 }
497
498 return true;
499 }
500
501 bool
SetBreakpointSite(BreakpointSiteSP & bp_site_sp)502 BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp)
503 {
504 m_bp_site_sp = bp_site_sp;
505 return true;
506 }
507
508 bool
ClearBreakpointSite()509 BreakpointLocation::ClearBreakpointSite ()
510 {
511 if (m_bp_site_sp.get())
512 {
513 m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(),
514 GetID(), m_bp_site_sp);
515 m_bp_site_sp.reset();
516 return true;
517 }
518 return false;
519 }
520
521 void
GetDescription(Stream * s,lldb::DescriptionLevel level)522 BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
523 {
524 SymbolContext sc;
525
526 // If the description level is "initial" then the breakpoint is printing out our initial state,
527 // and we should let it decide how it wants to print our label.
528 if (level != eDescriptionLevelInitial)
529 {
530 s->Indent();
531 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
532 }
533
534 if (level == lldb::eDescriptionLevelBrief)
535 return;
536
537 if (level != eDescriptionLevelInitial)
538 s->PutCString(": ");
539
540 if (level == lldb::eDescriptionLevelVerbose)
541 s->IndentMore();
542
543 if (m_address.IsSectionOffset())
544 {
545 m_address.CalculateSymbolContext(&sc);
546
547 if (level == lldb::eDescriptionLevelFull || level == eDescriptionLevelInitial)
548 {
549 s->PutCString("where = ");
550 sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false);
551 }
552 else
553 {
554 if (sc.module_sp)
555 {
556 s->EOL();
557 s->Indent("module = ");
558 sc.module_sp->GetFileSpec().Dump (s);
559 }
560
561 if (sc.comp_unit != NULL)
562 {
563 s->EOL();
564 s->Indent("compile unit = ");
565 static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s);
566
567 if (sc.function != NULL)
568 {
569 s->EOL();
570 s->Indent("function = ");
571 s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>"));
572 }
573
574 if (sc.line_entry.line > 0)
575 {
576 s->EOL();
577 s->Indent("location = ");
578 sc.line_entry.DumpStopContext (s, true);
579 }
580
581 }
582 else
583 {
584 // If we don't have a comp unit, see if we have a symbol we can print.
585 if (sc.symbol)
586 {
587 s->EOL();
588 s->Indent("symbol = ");
589 s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>"));
590 }
591 }
592 }
593 }
594
595 if (level == lldb::eDescriptionLevelVerbose)
596 {
597 s->EOL();
598 s->Indent();
599 }
600
601 if (m_address.IsSectionOffset() && (level == eDescriptionLevelFull || level == eDescriptionLevelInitial))
602 s->Printf (", ");
603 s->Printf ("address = ");
604
605 ExecutionContextScope *exe_scope = NULL;
606 Target *target = &m_owner.GetTarget();
607 if (target)
608 exe_scope = target->GetProcessSP().get();
609 if (exe_scope == NULL)
610 exe_scope = target;
611
612 if (eDescriptionLevelInitial)
613 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
614 else
615 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
616
617 if (level == lldb::eDescriptionLevelVerbose)
618 {
619 s->EOL();
620 s->Indent();
621 s->Printf("resolved = %s\n", IsResolved() ? "true" : "false");
622
623 s->Indent();
624 s->Printf ("hit count = %-4u\n", GetHitCount());
625
626 if (m_options_ap.get())
627 {
628 s->Indent();
629 m_options_ap->GetDescription (s, level);
630 s->EOL();
631 }
632 s->IndentLess();
633 }
634 else if (level != eDescriptionLevelInitial)
635 {
636 s->Printf(", %sresolved, hit count = %u ",
637 (IsResolved() ? "" : "un"),
638 GetHitCount());
639 if (m_options_ap.get())
640 {
641 m_options_ap->GetDescription (s, level);
642 }
643 }
644 }
645
646 void
Dump(Stream * s) const647 BreakpointLocation::Dump(Stream *s) const
648 {
649 if (s == NULL)
650 return;
651
652 s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64 " load addr = 0x%8.8" PRIx64 " state = %s type = %s breakpoint "
653 "hw_index = %i hit_count = %-4u ignore_count = %-4u",
654 GetID(),
655 GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(),
656 (uint64_t) m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()),
657 (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled",
658 IsHardware() ? "hardware" : "software",
659 GetHardwareIndex(),
660 GetHitCount(),
661 GetOptionsNoCreate()->GetIgnoreCount());
662 }
663
664 void
SendBreakpointLocationChangedEvent(lldb::BreakpointEventType eventKind)665 BreakpointLocation::SendBreakpointLocationChangedEvent (lldb::BreakpointEventType eventKind)
666 {
667 if (!m_being_created
668 && !m_owner.IsInternal()
669 && m_owner.GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
670 {
671 Breakpoint::BreakpointEventData *data = new Breakpoint::BreakpointEventData (eventKind,
672 m_owner.shared_from_this());
673 data->GetBreakpointLocationCollection().Add (shared_from_this());
674 m_owner.GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged, data);
675 }
676 }
677
678