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