BreakpointLocation.cpp revision 263363
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) :
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
56BreakpointLocation::~BreakpointLocation()
57{
58    ClearBreakpointSite();
59}
60
61lldb::addr_t
62BreakpointLocation::GetLoadAddress () const
63{
64    return m_address.GetOpcodeLoadAddress (&m_owner.GetTarget());
65}
66
67Address &
68BreakpointLocation::GetAddress ()
69{
70    return m_address;
71}
72
73Breakpoint &
74BreakpointLocation::GetBreakpoint ()
75{
76    return m_owner;
77}
78
79bool
80BreakpointLocation::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
90void
91BreakpointLocation::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
105void
106BreakpointLocation::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
120lldb::tid_t
121BreakpointLocation::GetThreadID ()
122{
123    if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
124        return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID();
125    else
126        return LLDB_INVALID_THREAD_ID;
127}
128
129void
130BreakpointLocation::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
145uint32_t
146BreakpointLocation::GetThreadIndex() const
147{
148    if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
149        return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetIndex();
150    else
151        return 0;
152}
153
154void
155BreakpointLocation::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
169const char *
170BreakpointLocation::GetThreadName () const
171{
172    if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
173        return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetName();
174    else
175        return NULL;
176}
177
178void
179BreakpointLocation::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
193const char *
194BreakpointLocation::GetQueueName () const
195{
196    if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
197        return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetQueueName();
198    else
199        return NULL;
200}
201
202bool
203BreakpointLocation::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
211void
212BreakpointLocation::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
221void
222BreakpointLocation::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
230void
231BreakpointLocation::ClearCallback ()
232{
233    GetLocationOptions()->ClearCallback();
234}
235
236void
237BreakpointLocation::SetCondition (const char *condition)
238{
239    GetLocationOptions()->SetCondition (condition);
240    SendBreakpointLocationChangedEvent (eBreakpointEventTypeConditionChanged);
241}
242
243const char *
244BreakpointLocation::GetConditionText (size_t *hash) const
245{
246    return GetOptionsNoCreate()->GetConditionText(hash);
247}
248
249bool
250BreakpointLocation::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
295    EvaluateExpressionOptions options;
296    options.SetUnwindOnError(true);
297    options.SetIgnoreBreakpoints(true);
298    options.SetRunOthers(true);
299
300    Error expr_error;
301
302    StreamString execution_errors;
303
304    ClangExpressionVariableSP result_variable_sp;
305
306    ExecutionResults result_code =
307    m_user_expression_sp->Execute(execution_errors,
308                                  exe_ctx,
309                                  options,
310                                  m_user_expression_sp,
311                                  result_variable_sp);
312
313    bool ret;
314
315    if (result_code == eExecutionCompleted)
316    {
317        if (!result_variable_sp)
318        {
319            ret = false;
320            error.SetErrorString("Expression did not return a result");
321            return false;
322        }
323
324        result_value_sp = result_variable_sp->GetValueObject();
325
326        if (result_value_sp)
327        {
328            Scalar scalar_value;
329            if (result_value_sp->ResolveValue (scalar_value))
330            {
331                if (scalar_value.ULongLong(1) == 0)
332                    ret = false;
333                else
334                    ret = true;
335                if (log)
336                    log->Printf("Condition successfully evaluated, result is %s.\n",
337                                ret ? "true" : "false");
338            }
339            else
340            {
341                ret = false;
342                error.SetErrorString("Failed to get an integer result from the expression");
343            }
344        }
345        else
346        {
347            ret = false;
348            error.SetErrorString("Failed to get any result from the expression");
349        }
350    }
351    else
352    {
353        ret = false;
354        error.SetErrorStringWithFormat("Couldn't execute expression:\n%s", execution_errors.GetData());
355    }
356
357    return ret;
358}
359
360uint32_t
361BreakpointLocation::GetIgnoreCount ()
362{
363    return GetOptionsNoCreate()->GetIgnoreCount();
364}
365
366void
367BreakpointLocation::SetIgnoreCount (uint32_t n)
368{
369    GetLocationOptions()->SetIgnoreCount(n);
370    SendBreakpointLocationChangedEvent (eBreakpointEventTypeIgnoreChanged);
371}
372
373void
374BreakpointLocation::DecrementIgnoreCount()
375{
376    if (m_options_ap.get() != NULL)
377    {
378        uint32_t loc_ignore = m_options_ap->GetIgnoreCount();
379        if (loc_ignore != 0)
380            m_options_ap->SetIgnoreCount(loc_ignore - 1);
381    }
382}
383
384bool
385BreakpointLocation::IgnoreCountShouldStop()
386{
387    if (m_options_ap.get() != NULL)
388    {
389        uint32_t loc_ignore = m_options_ap->GetIgnoreCount();
390        if (loc_ignore != 0)
391        {
392            m_owner.DecrementIgnoreCount();
393            DecrementIgnoreCount();          // Have to decrement our owners' ignore count, since it won't get a
394                                             // chance to.
395            return false;
396        }
397    }
398    return true;
399}
400
401const BreakpointOptions *
402BreakpointLocation::GetOptionsNoCreate () const
403{
404    if (m_options_ap.get() != NULL)
405        return m_options_ap.get();
406    else
407        return m_owner.GetOptions ();
408}
409
410BreakpointOptions *
411BreakpointLocation::GetLocationOptions ()
412{
413    // If we make the copy we don't copy the callbacks because that is potentially
414    // expensive and we don't want to do that for the simple case where someone is
415    // just disabling the location.
416    if (m_options_ap.get() == NULL)
417        m_options_ap.reset(BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions ()));
418
419    return m_options_ap.get();
420}
421
422bool
423BreakpointLocation::ValidForThisThread (Thread *thread)
424{
425    return thread->MatchesSpec(GetOptionsNoCreate()->GetThreadSpecNoCreate());
426}
427
428// RETURNS - true if we should stop at this breakpoint, false if we
429// should continue.  Note, we don't check the thread spec for the breakpoint
430// here, since if the breakpoint is not for this thread, then the event won't
431// even get reported, so the check is redundant.
432
433bool
434BreakpointLocation::ShouldStop (StoppointCallbackContext *context)
435{
436    bool should_stop = true;
437    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
438
439    IncrementHitCount();
440
441    if (!IsEnabled())
442        return false;
443
444    if (!IgnoreCountShouldStop())
445        return false;
446
447    if (!m_owner.IgnoreCountShouldStop())
448        return false;
449
450    // We only run synchronous callbacks in ShouldStop:
451    context->is_synchronous = true;
452    should_stop = InvokeCallback (context);
453
454    if (log)
455    {
456        StreamString s;
457        GetDescription (&s, lldb::eDescriptionLevelVerbose);
458        log->Printf ("Hit breakpoint location: %s, %s.\n", s.GetData(), should_stop ? "stopping" : "continuing");
459    }
460
461    return should_stop;
462}
463
464bool
465BreakpointLocation::IsResolved () const
466{
467    return m_bp_site_sp.get() != NULL;
468}
469
470lldb::BreakpointSiteSP
471BreakpointLocation::GetBreakpointSite() const
472{
473    return m_bp_site_sp;
474}
475
476bool
477BreakpointLocation::ResolveBreakpointSite ()
478{
479    if (m_bp_site_sp)
480        return true;
481
482    Process *process = m_owner.GetTarget().GetProcessSP().get();
483    if (process == NULL)
484        return false;
485
486    lldb::break_id_t new_id = process->CreateBreakpointSite (shared_from_this(), m_owner.IsHardware());
487
488    if (new_id == LLDB_INVALID_BREAK_ID)
489    {
490        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
491        if (log)
492            log->Warning ("Tried to add breakpoint site at 0x%" PRIx64 " but it was already present.\n",
493                          m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()));
494        return false;
495    }
496
497    return true;
498}
499
500bool
501BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp)
502{
503    m_bp_site_sp = bp_site_sp;
504    return true;
505}
506
507bool
508BreakpointLocation::ClearBreakpointSite ()
509{
510    if (m_bp_site_sp.get())
511    {
512        m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(),
513                                                                           GetID(), m_bp_site_sp);
514        m_bp_site_sp.reset();
515        return true;
516    }
517    return false;
518}
519
520void
521BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
522{
523    SymbolContext sc;
524
525    // If the description level is "initial" then the breakpoint is printing out our initial state,
526    // and we should let it decide how it wants to print our label.
527    if (level != eDescriptionLevelInitial)
528    {
529        s->Indent();
530        BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
531    }
532
533    if (level == lldb::eDescriptionLevelBrief)
534        return;
535
536    if (level != eDescriptionLevelInitial)
537        s->PutCString(": ");
538
539    if (level == lldb::eDescriptionLevelVerbose)
540        s->IndentMore();
541
542    if (m_address.IsSectionOffset())
543    {
544        m_address.CalculateSymbolContext(&sc);
545
546        if (level == lldb::eDescriptionLevelFull || level == eDescriptionLevelInitial)
547        {
548            s->PutCString("where = ");
549            sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false);
550        }
551        else
552        {
553            if (sc.module_sp)
554            {
555                s->EOL();
556                s->Indent("module = ");
557                sc.module_sp->GetFileSpec().Dump (s);
558            }
559
560            if (sc.comp_unit != NULL)
561            {
562                s->EOL();
563                s->Indent("compile unit = ");
564                static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s);
565
566                if (sc.function != NULL)
567                {
568                    s->EOL();
569                    s->Indent("function = ");
570                    s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>"));
571                }
572
573                if (sc.line_entry.line > 0)
574                {
575                    s->EOL();
576                    s->Indent("location = ");
577                    sc.line_entry.DumpStopContext (s, true);
578                }
579
580            }
581            else
582            {
583                // If we don't have a comp unit, see if we have a symbol we can print.
584                if (sc.symbol)
585                {
586                    s->EOL();
587                    s->Indent("symbol = ");
588                    s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>"));
589                }
590            }
591        }
592    }
593
594    if (level == lldb::eDescriptionLevelVerbose)
595    {
596        s->EOL();
597        s->Indent();
598    }
599
600    if (m_address.IsSectionOffset() && (level == eDescriptionLevelFull || level == eDescriptionLevelInitial))
601        s->Printf (", ");
602    s->Printf ("address = ");
603
604    ExecutionContextScope *exe_scope = NULL;
605    Target *target = &m_owner.GetTarget();
606    if (target)
607        exe_scope = target->GetProcessSP().get();
608    if (exe_scope == NULL)
609        exe_scope = target;
610
611    if (eDescriptionLevelInitial)
612        m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
613    else
614        m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
615
616    if (level == lldb::eDescriptionLevelVerbose)
617    {
618        s->EOL();
619        s->Indent();
620        s->Printf("resolved = %s\n", IsResolved() ? "true" : "false");
621
622        s->Indent();
623        s->Printf ("hit count = %-4u\n", GetHitCount());
624
625        if (m_options_ap.get())
626        {
627            s->Indent();
628            m_options_ap->GetDescription (s, level);
629            s->EOL();
630        }
631        s->IndentLess();
632    }
633    else if (level != eDescriptionLevelInitial)
634    {
635        s->Printf(", %sresolved, hit count = %u ",
636                  (IsResolved() ? "" : "un"),
637                  GetHitCount());
638        if (m_options_ap.get())
639        {
640            m_options_ap->GetDescription (s, level);
641        }
642    }
643}
644
645void
646BreakpointLocation::Dump(Stream *s) const
647{
648    if (s == NULL)
649        return;
650
651    s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64 "  load addr = 0x%8.8" PRIx64 "  state = %s  type = %s breakpoint  "
652              "hw_index = %i  hit_count = %-4u  ignore_count = %-4u",
653              GetID(),
654              GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(),
655              (uint64_t) m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()),
656              (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled",
657              IsHardware() ? "hardware" : "software",
658              GetHardwareIndex(),
659              GetHitCount(),
660              GetOptionsNoCreate()->GetIgnoreCount());
661}
662
663void
664BreakpointLocation::SendBreakpointLocationChangedEvent (lldb::BreakpointEventType eventKind)
665{
666    if (!m_being_created
667        && !m_owner.IsInternal()
668        && m_owner.GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
669    {
670        Breakpoint::BreakpointEventData *data = new Breakpoint::BreakpointEventData (eventKind,
671                                                                                     m_owner.shared_from_this());
672        data->GetBreakpointLocationCollection().Add (shared_from_this());
673        m_owner.GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged, data);
674    }
675}
676
677