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