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