BreakpointLocation.cpp revision 269024
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        {
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    ExecutionResults 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 == eExecutionCompleted)
329    {
330        if (!result_variable_sp)
331        {
332            ret = false;
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        m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(),
526                                                                           GetID(), m_bp_site_sp);
527        m_bp_site_sp.reset();
528        return true;
529    }
530    return false;
531}
532
533void
534BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
535{
536    SymbolContext sc;
537
538    // If the description level is "initial" then the breakpoint is printing out our initial state,
539    // and we should let it decide how it wants to print our label.
540    if (level != eDescriptionLevelInitial)
541    {
542        s->Indent();
543        BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
544    }
545
546    if (level == lldb::eDescriptionLevelBrief)
547        return;
548
549    if (level != eDescriptionLevelInitial)
550        s->PutCString(": ");
551
552    if (level == lldb::eDescriptionLevelVerbose)
553        s->IndentMore();
554
555    if (m_address.IsSectionOffset())
556    {
557        m_address.CalculateSymbolContext(&sc);
558
559        if (level == lldb::eDescriptionLevelFull || level == eDescriptionLevelInitial)
560        {
561            if (IsReExported())
562                s->PutCString ("re-exported target = ");
563            else
564                s->PutCString("where = ");
565            sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false);
566        }
567        else
568        {
569            if (sc.module_sp)
570            {
571                s->EOL();
572                s->Indent("module = ");
573                sc.module_sp->GetFileSpec().Dump (s);
574            }
575
576            if (sc.comp_unit != NULL)
577            {
578                s->EOL();
579                s->Indent("compile unit = ");
580                static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s);
581
582                if (sc.function != NULL)
583                {
584                    s->EOL();
585                    s->Indent("function = ");
586                    s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>"));
587                }
588
589                if (sc.line_entry.line > 0)
590                {
591                    s->EOL();
592                    s->Indent("location = ");
593                    sc.line_entry.DumpStopContext (s, true);
594                }
595
596            }
597            else
598            {
599                // If we don't have a comp unit, see if we have a symbol we can print.
600                if (sc.symbol)
601                {
602                    s->EOL();
603                    if (IsReExported())
604                        s->Indent ("re-exported target = ");
605                    else
606                        s->Indent("symbol = ");
607                    s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>"));
608                }
609            }
610        }
611    }
612
613    if (level == lldb::eDescriptionLevelVerbose)
614    {
615        s->EOL();
616        s->Indent();
617    }
618
619    if (m_address.IsSectionOffset() && (level == eDescriptionLevelFull || level == eDescriptionLevelInitial))
620        s->Printf (", ");
621    s->Printf ("address = ");
622
623    ExecutionContextScope *exe_scope = NULL;
624    Target *target = &m_owner.GetTarget();
625    if (target)
626        exe_scope = target->GetProcessSP().get();
627    if (exe_scope == NULL)
628        exe_scope = target;
629
630    if (eDescriptionLevelInitial)
631        m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
632    else
633        m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
634
635    if (IsIndirect() && m_bp_site_sp)
636    {
637        Address resolved_address;
638        resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target);
639        Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol();
640        if (resolved_symbol)
641        {
642            if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)
643                s->Printf (", ");
644            else if (level == lldb::eDescriptionLevelVerbose)
645            {
646                s->EOL();
647                s->Indent();
648            }
649            s->Printf ("indirect target = %s", resolved_symbol->GetName().GetCString());
650        }
651    }
652
653    if (level == lldb::eDescriptionLevelVerbose)
654    {
655        s->EOL();
656        s->Indent();
657        s->Printf("resolved = %s\n", IsResolved() ? "true" : "false");
658
659        s->Indent();
660        s->Printf ("hit count = %-4u\n", GetHitCount());
661
662        if (m_options_ap.get())
663        {
664            s->Indent();
665            m_options_ap->GetDescription (s, level);
666            s->EOL();
667        }
668        s->IndentLess();
669    }
670    else if (level != eDescriptionLevelInitial)
671    {
672        s->Printf(", %sresolved, hit count = %u ",
673                  (IsResolved() ? "" : "un"),
674                  GetHitCount());
675        if (m_options_ap.get())
676        {
677            m_options_ap->GetDescription (s, level);
678        }
679    }
680}
681
682void
683BreakpointLocation::Dump(Stream *s) const
684{
685    if (s == NULL)
686        return;
687
688    s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64 "  load addr = 0x%8.8" PRIx64 "  state = %s  type = %s breakpoint  "
689              "hw_index = %i  hit_count = %-4u  ignore_count = %-4u",
690              GetID(),
691              GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(),
692              (uint64_t) m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()),
693              (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled",
694              IsHardware() ? "hardware" : "software",
695              GetHardwareIndex(),
696              GetHitCount(),
697              GetOptionsNoCreate()->GetIgnoreCount());
698}
699
700void
701BreakpointLocation::SendBreakpointLocationChangedEvent (lldb::BreakpointEventType eventKind)
702{
703    if (!m_being_created
704        && !m_owner.IsInternal()
705        && m_owner.GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
706    {
707        Breakpoint::BreakpointEventData *data = new Breakpoint::BreakpointEventData (eventKind,
708                                                                                     m_owner.shared_from_this());
709        data->GetBreakpointLocationCollection().Add (shared_from_this());
710        m_owner.GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged, data);
711    }
712}
713
714